Repository: trafficserver Updated Branches: refs/heads/master 18ebfbaa5 -> 97068fb84
TS-2039: Clean up coverity reported leaks in SSL examples and experimental plugin. Tidy up licenses and code standard issues. This closes #129 Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/97068fb8 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/97068fb8 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/97068fb8 Branch: refs/heads/master Commit: 97068fb8490901a154048f7597c918af8eaeafc2 Parents: 18ebfba Author: shinrich <shinr...@network-geographics.com> Authored: Wed Oct 1 10:16:42 2014 -0500 Committer: Alan M. Carroll <a...@apache.org> Committed: Thu Oct 2 09:17:08 2014 -0500 ---------------------------------------------------------------------- example/ssl-preaccept/ssl-preaccept.cc | 106 +++++++++++-------- example/ssl-sni-whitelist/ssl-sni-whitelist.cc | 97 ++++++++++------- example/ssl-sni/ssl-sni.cc | 101 ++++++++++-------- .../ssl_cert_loader/ssl-cert-loader.cc | 64 +++++------ 4 files changed, 200 insertions(+), 168 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/97068fb8/example/ssl-preaccept/ssl-preaccept.cc ---------------------------------------------------------------------- diff --git a/example/ssl-preaccept/ssl-preaccept.cc b/example/ssl-preaccept/ssl-preaccept.cc index c67ba8c..c0f0ce8 100644 --- a/example/ssl-preaccept/ssl-preaccept.cc +++ b/example/ssl-preaccept/ssl-preaccept.cc @@ -1,10 +1,29 @@ -/** @file - SSL Preaccept test plugin - Implements blind tunneling based on the client IP address - The client ip addresses are specified in the plugin's - config file as an array of IP addresses or IP address ranges under the - key "client-blind-tunnel" -*/ +/** @file + + SSL Preaccept test plugin + Implements blind tunneling based on the client IP address + The client ip addresses are specified in the plugin's + config file as an array of IP addresses or IP address ranges under the + key "client-blind-tunnel" + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ # include <stdio.h> # include <memory.h> @@ -12,6 +31,7 @@ # include <ts/ts.h> # include <tsconfig/TsValue.h> # include <ts/ink_inet.h> +# include <getopt.h> using ts::config::Configuration; using ts::config::Value; @@ -29,7 +49,8 @@ IpRangeQueue ClientBlindTunnelIp; Configuration Config; // global configuration void -Parse_Addr_String(ts::ConstBuffer const &text, IpRange &range) { +Parse_Addr_String(ts::ConstBuffer const &text, IpRange &range) +{ IpAddr newAddr; std::string textstr(text._ptr, text._size); // Is there a hyphen? @@ -48,7 +69,8 @@ Parse_Addr_String(ts::ConstBuffer const &text, IpRange &range) { } /// Get a string value from a config node. -void Load_Config_Value(Value const& parent, char const* name, IpRangeQueue &addrs) { +void Load_Config_Value(Value const& parent, char const* name, IpRangeQueue &addrs) +{ Value v = parent[name]; std::string zret; IpRange ipRange; @@ -67,7 +89,8 @@ void Load_Config_Value(Value const& parent, char const* name, IpRangeQueue &addr int -Load_Config_File() { +Load_Config_File() +{ ts::Rv<Configuration> cv = Configuration::loadFromPath(ConfigPath.c_str()); if (!cv.isOK()) { TSError(PCP "Failed to parse %s as TSConfig format", ConfigPath.c_str()); @@ -78,36 +101,8 @@ Load_Config_File() { } int -Load_Configuration(int argc, const char *argv[]) { -ts::ConstBuffer text; - std::string s; // temp holder. - TSMgmtString config_path = NULL; - - // get the path to the config file if one was specified - static char const * const CONFIG_ARG = "--config="; - int arg_idx; - for (arg_idx = 0; arg_idx < argc; arg_idx++) { - if (0 == memcmp(argv[arg_idx], CONFIG_ARG, strlen(CONFIG_ARG))) { - config_path = TSstrdup(argv[arg_idx] + strlen(CONFIG_ARG)); - TSDebug(PN, "Found config path %s", config_path); - } - } - if (NULL == config_path) { - static char const * const DEFAULT_CONFIG_PATH = "ssl_preaccept.config"; - config_path = TSstrdup(DEFAULT_CONFIG_PATH); - TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); - } - - // translate relative paths to absolute - if (config_path[0] != '/') { - ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(config_path); - } else { - ConfigPath = config_path; - } - - // free up the path - TSfree(config_path); - +Load_Configuration() +{ int ret = Load_Config_File(); if (ret != 0) { TSError(PCP "Failed to load the config file, check debug output for errata"); @@ -121,7 +116,8 @@ ts::ConstBuffer text; } int -CB_Pre_Accept(TSCont, TSEvent event, void *edata) { +CB_Pre_Accept(TSCont, TSEvent event, void *edata) +{ TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata); IpAddr ip(TSNetVConnLocalAddrGet(ssl_vc)); char buff[INET6_ADDRSTRLEN]; @@ -149,8 +145,7 @@ CB_Pre_Accept(TSCont, TSEvent event, void *edata) { TSDebug("skh", "Blind tunnel"); // Push everything to blind tunnel TSVConnTunnel(ssl_vc); - } - else { + } else { TSDebug("skh", "Proxy tunnel"); } @@ -163,20 +158,41 @@ CB_Pre_Accept(TSCont, TSEvent event, void *edata) { // Called by ATS as our initialization point void -TSPluginInit(int argc, const char *argv[]) { +TSPluginInit(int argc, const char *argv[]) +{ bool success = false; TSPluginRegistrationInfo info; TSCont cb_pa = 0; // pre-accept callback continuation + static const struct option longopt[] = { + { const_cast<char *>("config"), required_argument, NULL, 'c' }, + { NULL, no_argument, NULL, '\0' } + }; info.plugin_name = const_cast<char*>("SSL Preaccept test"); info.vendor_name = const_cast<char*>("Network Geographics"); info.support_email = const_cast<char*>("shinr...@network-geographics.com"); + int opt = 0; + while (opt >= 0) { + opt = getopt_long(argc, (char * const *)argv, "c:", longopt, NULL); + switch (opt) { + case 'c': + ConfigPath = optarg; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(optarg); + break; + } + } + if (ConfigPath.length() == 0) { + static char const * const DEFAULT_CONFIG_PATH = "ssl_preaccept.config"; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(DEFAULT_CONFIG_PATH); + TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); + } + if (TS_SUCCESS != TSPluginRegister(TS_SDK_VERSION_2_0, &info)) { TSError(PCP "registration failed."); } else if (TSTrafficServerVersionGetMajor() < 2) { TSError(PCP "requires Traffic Server 2.0 or later."); - } else if (0 > Load_Configuration(argc, argv)) { + } else if (0 > Load_Configuration()) { TSError(PCP "Failed to load config file."); } else if (0 == (cb_pa = TSContCreate(&CB_Pre_Accept, TSMutexCreate()))) { TSError(PCP "Failed to pre-accept callback."); http://git-wip-us.apache.org/repos/asf/trafficserver/blob/97068fb8/example/ssl-sni-whitelist/ssl-sni-whitelist.cc ---------------------------------------------------------------------- diff --git a/example/ssl-sni-whitelist/ssl-sni-whitelist.cc b/example/ssl-sni-whitelist/ssl-sni-whitelist.cc index 1ef5275..496e950 100644 --- a/example/ssl-sni-whitelist/ssl-sni-whitelist.cc +++ b/example/ssl-sni-whitelist/ssl-sni-whitelist.cc @@ -1,8 +1,27 @@ /** @file - SSL SNI white list plugin - If the server name and IP address are not in the ssl_multicert.config - go head and blind tunnel it. -*/ + + SSL SNI white list plugin + If the server name and IP address are not in the ssl_multicert.config + go head and blind tunnel it. + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ # include <stdio.h> # include <memory.h> @@ -11,6 +30,7 @@ # include <ink_config.h> # include <tsconfig/TsValue.h> # include <openssl/ssl.h> +# include <getopt.h> using ts::config::Configuration; using ts::config::Value; @@ -27,7 +47,8 @@ std::string ConfigPath; Configuration Config; // global configuration int -Load_Config_File() { +Load_Config_File() +{ ts::Rv<Configuration> cv = Configuration::loadFromPath(ConfigPath.c_str()); if (!cv.isOK()) { TSError(PCP "Failed to parse %s as TSConfig format", ConfigPath.c_str()); @@ -38,36 +59,8 @@ Load_Config_File() { } int -Load_Configuration(int argc, const char *argv[]) { -ts::ConstBuffer text; - std::string s; // temp holder. - TSMgmtString config_path = NULL; - - // get the path to the config file if one was specified - static char const * const CONFIG_ARG = "--config="; - int arg_idx; - for (arg_idx = 0; arg_idx < argc; arg_idx++) { - if (0 == memcmp(argv[arg_idx], CONFIG_ARG, strlen(CONFIG_ARG))) { - config_path = TSstrdup(argv[arg_idx] + strlen(CONFIG_ARG)); - TSDebug(PN, "Found config path %s", config_path); - } - } - if (NULL == config_path) { - static char const * const DEFAULT_CONFIG_PATH = "ssl_sni_whitelist.config"; - config_path = TSstrdup(DEFAULT_CONFIG_PATH); - TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); - } - - // translate relative paths to absolute - if (config_path[0] != '/') { - ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(config_path); - } else { - ConfigPath = config_path; - } - - // free up the path - TSfree(config_path); - +Load_Configuration() +{ int ret = Load_Config_File(); if (ret != 0) { TSError(PCP "Failed to load the config file, check debug output for errata"); @@ -77,7 +70,8 @@ ts::ConstBuffer text; } int -CB_servername_whitelist(TSCont /* contp */, TSEvent /* event */, void *edata) { +CB_servername_whitelist(TSCont /* contp */, TSEvent /* event */, void *edata) +{ TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata); TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast<SSL *>(sslobj); @@ -88,8 +82,7 @@ CB_servername_whitelist(TSCont /* contp */, TSEvent /* event */, void *edata) { TSSslContext ctxobj = TSSslContextFindByName(servername); if (ctxobj != NULL) { do_blind_tunnel = false; - } - else { + } else { // Look up by destination address ctxobj = TSSslContextFindByAddr(TSNetVConnRemoteAddrGet(ssl_vc)); if (ctxobj != NULL) { @@ -110,20 +103,41 @@ CB_servername_whitelist(TSCont /* contp */, TSEvent /* event */, void *edata) { // Called by ATS as our initialization point void -TSPluginInit(int argc, const char *argv[]) { +TSPluginInit(int argc, const char *argv[]) +{ bool success = false; TSPluginRegistrationInfo info; TSCont cb_sni = 0; // sni callback continuation + static const struct option longopt[] = { + { const_cast<char *>("config"), required_argument, NULL, 'c' }, + { NULL, no_argument, NULL, '\0' } + }; info.plugin_name = const_cast<char*>("SSL SNI whitelist"); info.vendor_name = const_cast<char*>("Network Geographics"); info.support_email = const_cast<char*>("shinr...@network-geographics.com"); + int opt = 0; + while (opt >= 0) { + opt = getopt_long(argc, (char * const *)argv, "c:", longopt, NULL); + switch (opt) { + case 'c': + ConfigPath = optarg; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(optarg); + break; + } + } + if (ConfigPath.length() == 0) { + static char const * const DEFAULT_CONFIG_PATH = "ssl_sni_whitelist.config"; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(DEFAULT_CONFIG_PATH); + TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); + } + if (TS_SUCCESS != TSPluginRegister(TS_SDK_VERSION_2_0, &info)) { TSError(PCP "registration failed."); } else if (TSTrafficServerVersionGetMajor() < 2) { TSError(PCP "requires Traffic Server 2.0 or later."); - } else if (0 > Load_Configuration(argc, argv)) { + } else if (0 > Load_Configuration()) { TSError(PCP "Failed to load config file."); } else if (0 == (cb_sni = TSContCreate(&CB_servername_whitelist, TSMutexCreate()))) { TSError(PCP "Failed to create SNI callback."); @@ -144,7 +158,8 @@ TSPluginInit(int argc, const char *argv[]) { # else // ! TS_USE_TLS_SNI void -TSPluginInit(int, const char *[]) { +TSPluginInit(int, const char *[]) +{ TSError(PCP "requires TLS SNI which is not available."); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/97068fb8/example/ssl-sni/ssl-sni.cc ---------------------------------------------------------------------- diff --git a/example/ssl-sni/ssl-sni.cc b/example/ssl-sni/ssl-sni.cc index fb31f6b..0367d5f 100644 --- a/example/ssl-sni/ssl-sni.cc +++ b/example/ssl-sni/ssl-sni.cc @@ -1,10 +1,30 @@ -/** @file - SSL Preaccept test plugin - Implements blind tunneling based on the client IP address - The client ip addresses are specified in the plugin's - config file as an array of IP addresses or IP address ranges under the - key "client-blind-tunnel" -*/ +/** + @file + SSL Preaccept test plugin + Implements blind tunneling based on the client IP address + The client ip addresses are specified in the plugin's + config file as an array of IP addresses or IP address ranges under the + key "client-blind-tunnel" + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + # include <stdio.h> # include <memory.h> @@ -13,6 +33,7 @@ # include <ink_config.h> # include <tsconfig/TsValue.h> # include <openssl/ssl.h> +# include <getopt.h> using ts::config::Configuration; using ts::config::Value; @@ -29,7 +50,8 @@ std::string ConfigPath; Configuration Config; // global configuration int -Load_Config_File() { +Load_Config_File() +{ ts::Rv<Configuration> cv = Configuration::loadFromPath(ConfigPath.c_str()); if (!cv.isOK()) { TSError(PCP "Failed to parse %s as TSConfig format", ConfigPath.c_str()); @@ -40,36 +62,8 @@ Load_Config_File() { } int -Load_Configuration(int argc, const char *argv[]) { -ts::ConstBuffer text; - std::string s; // temp holder. - TSMgmtString config_path = NULL; - - // get the path to the config file if one was specified - static char const * const CONFIG_ARG = "--config="; - int arg_idx; - for (arg_idx = 0; arg_idx < argc; arg_idx++) { - if (0 == memcmp(argv[arg_idx], CONFIG_ARG, strlen(CONFIG_ARG))) { - config_path = TSstrdup(argv[arg_idx] + strlen(CONFIG_ARG)); - TSDebug(PN, "Found config path %s", config_path); - } - } - if (NULL == config_path) { - static char const * const DEFAULT_CONFIG_PATH = "ssl_sni.config"; - config_path = TSstrdup(DEFAULT_CONFIG_PATH); - TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); - } - - // translate relative paths to absolute - if (config_path[0] != '/') { - ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(config_path); - } else { - ConfigPath = config_path; - } - - // free up the path - TSfree(config_path); - +Load_Configuration() +{ int ret = Load_Config_File(); if (ret != 0) { TSError(PCP "Failed to load the config file, check debug output for errata"); @@ -88,7 +82,8 @@ ts::ConstBuffer text; this connection. */ int -CB_servername(TSCont /* contp */, TSEvent /* event */, void *edata) { +CB_servername(TSCont /* contp */, TSEvent /* event */, void *edata) +{ TSVConn ssl_vc = reinterpret_cast<TSVConn>(edata); TSSslConnection sslobj = TSVConnSSLConnectionGet(ssl_vc); SSL *ssl = reinterpret_cast<SSL *>(sslobj); @@ -131,20 +126,41 @@ CB_servername(TSCont /* contp */, TSEvent /* event */, void *edata) { // Called by ATS as our initialization point void -TSPluginInit(int argc, const char *argv[]) { +TSPluginInit(int argc, const char *argv[]) +{ bool success = false; TSPluginRegistrationInfo info; TSCont cb_sni = 0; // sni callback continuation + static const struct option longopt[] = { + { const_cast<char *>("config"), required_argument, NULL, 'c' }, + { NULL, no_argument, NULL, '\0' } + }; info.plugin_name = const_cast<char*>("SSL SNI callback test"); info.vendor_name = const_cast<char*>("Network Geographics"); info.support_email = const_cast<char*>("shinr...@network-geographics.com"); + int opt = 0; + while (opt >= 0) { + opt = getopt_long(argc, (char * const *)argv, "c:", longopt, NULL); + switch (opt) { + case 'c': + ConfigPath = optarg; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(optarg); + break; + } + } + if (ConfigPath.length() == 0) { + static char const * const DEFAULT_CONFIG_PATH = "ssl_sni.config"; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(DEFAULT_CONFIG_PATH); + TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); + } + if (TS_SUCCESS != TSPluginRegister(TS_SDK_VERSION_2_0, &info)) { TSError(PCP "registration failed."); } else if (TSTrafficServerVersionGetMajor() < 2) { TSError(PCP "requires Traffic Server 2.0 or later."); - } else if (0 > Load_Configuration(argc, argv)) { + } else if (0 > Load_Configuration()) { TSError(PCP "Failed to load config file."); } else if (0 == (cb_sni = TSContCreate(&CB_servername, TSMutexCreate()))) { TSError(PCP "Failed to create SNI callback."); @@ -165,7 +181,8 @@ TSPluginInit(int argc, const char *argv[]) { # else // ! TS_USE_TLS_SNI void -TSPluginInit(int, const char *[]) { +TSPluginInit(int, const char *[]) +{ TSError(PCP "requires TLS SNI which is not available."); } http://git-wip-us.apache.org/repos/asf/trafficserver/blob/97068fb8/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc ---------------------------------------------------------------------- diff --git a/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc b/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc index 1aaf3d0..7bf72cc 100644 --- a/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc +++ b/plugins/experimental/ssl_cert_loader/ssl-cert-loader.cc @@ -32,6 +32,7 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> #include <ts/ink_inet.h> +#include <getopt.h> #include <ts/IpMap.h> #include "domain-tree.h" @@ -129,42 +130,6 @@ struct ParsedSslValues { void Parse_Config_Rules(Value &parent, ParsedSslValues &orig_values); int -Load_Configuration_Args(int argc, const char *argv[]) -{ - ts::ConstBuffer text; - std::string s; // temp holder. - TSMgmtString config_path = NULL; - // get the path to the config file if one was specified - static char const * const CONFIG_ARG = "--config="; - - for (int arg_idx = 0; arg_idx < argc; arg_idx++) { - if (0 == memcmp(argv[arg_idx], CONFIG_ARG, strlen(CONFIG_ARG))) { - config_path = TSstrdup(argv[arg_idx] + strlen(CONFIG_ARG)); - TSDebug(PN, "Found config path %s", config_path); - } - } - if (NULL == config_path) { - static char const * const DEFAULT_CONFIG_PATH = "ssl_start.cfg"; - - config_path = TSstrdup(DEFAULT_CONFIG_PATH); - TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); - } - - // translate relative paths to absolute - if (config_path[0] != '/') { - ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(config_path); - } else { - ConfigPath = config_path; - } - - TSDebug(PN, "Load from %s", ConfigPath.c_str()); - // free up the path - TSfree(config_path); - - return 0; -} - -int Load_Configuration() { int ret = Load_Config_File(); @@ -527,17 +492,36 @@ TSPluginInit(int argc, const char *argv[]) TSCont cb_pa = 0; // pre-accept callback continuation TSCont cb_lc = 0; // life cycle callback continuuation TSCont cb_sni = 0; // SNI callback continuuation + static const struct option longopt[] = { + { const_cast<char *>("config"), required_argument, NULL, 'c' }, + { NULL, no_argument, NULL, '\0' } + }; + info.plugin_name = const_cast<char*>("SSL Certificate Loader"); info.vendor_name = const_cast<char*>("Network Geographics"); info.support_email = const_cast<char*>("shinr...@network-geographics.com"); + int opt = 0; + while (opt >= 0) { + opt = getopt_long(argc, (char * const *)argv, "c:", longopt, NULL); + switch (opt) { + case 'c': + ConfigPath = optarg; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(optarg); + break; + } + } + if (ConfigPath.length() == 0) { + static char const * const DEFAULT_CONFIG_PATH = "ssl_start.cfg"; + ConfigPath = std::string(TSConfigDirGet()) + '/' + std::string(DEFAULT_CONFIG_PATH); + TSDebug(PN, "No config path set in arguments, using default: %s", DEFAULT_CONFIG_PATH); + } + if (TS_SUCCESS != TSPluginRegister(TS_SDK_VERSION_2_0, &info)) { TSError(PCP "registration failed."); - } else if (TSTrafficServerVersionGetMajor() < 2) { - TSError(PCP "requires Traffic Server 2.0 or later."); - } else if (0 > Load_Configuration_Args(argc, argv)) { - TSError(PCP "Failed to load config file."); + } else if (TSTrafficServerVersionGetMajor() < 5) { + TSError(PCP "requires Traffic Server 5.0 or later."); } else if (0 == (cb_pa = TSContCreate(&CB_Pre_Accept, TSMutexCreate()))) { TSError(PCP "Failed to pre-accept callback."); } else if (0 == (cb_lc = TSContCreate(&CB_Life_Cycle, TSMutexCreate()))) {