OSDN Git Service

formatted all files with 'astyle -A8 -HUpc -k3 -z2 -r ./*.cpp ./*.c ./*.h'.
[ultramonkey-l7/ultramonkey-l7-v3.git] / l7vsd / src / l7vsadm.cpp
1 /*!
2  * @file  l7vsadm.cpp
3  * @brief l7vsadm command is l7vsd control application
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2009  NTT COMWARE Corporation.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24
25 #include <iostream>
26 #include <sstream>
27 #include <exception>
28 #include <csignal>
29 #include <boost/bind.hpp>
30 #include <boost/archive/text_oarchive.hpp>
31 #include <boost/archive/text_iarchive.hpp>
32 #include <boost/format.hpp>
33 #include <boost/algorithm/string.hpp>
34 #include <sys/file.h>
35 #include "l7vsadm.h"
36 #include "logger.h"
37 #include "parameter.h"
38 #include "protocol_module_control.h"
39 #include "schedule_module_control.h"
40 #include "virtualservice_element.h"
41 #include "logger_access_manager.h"
42
43 #define VS_CONTACT_CLASS_SSL (0x00000001)
44
45 // global function prototype
46 static void sig_exit_handler(int sig);
47 static int  set_sighandler(int sig, void (*handler)(int));
48 static int  set_sighandlers();
49
50 // global variables
51 static bool signal_flag = false;
52 static int  received_sig = 0;
53
54 //
55 // command functions.
56 //
57 //! list command parsing.
58 //! @param[in] request command
59 //! @param[in] argument count
60 //! @param[in] argument value
61 bool l7vs::l7vsadm::parse_list_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
62 {
63         Logger logger(LOG_CAT_L7VSADM_COMMON, 1, "l7vsadm::parse_list_func", __FILE__, __LINE__);
64
65         request.command = cmd; // set command
66         if (argc < 3) {
67                 return true; // option is none. this pattern is true
68         } else if (argc > 3) {
69                 std::stringstream buf;
70                 buf << "Argument argc is illegal for " << argv[1] << " command.";
71                 l7vsadm_err.setter(true, buf.str());
72                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 117, buf.str(), __FILE__, __LINE__);
73                 return false;
74         }
75
76         for (int pos = 2; pos < argc; ++pos) { //search option function from argv strings
77                 parse_opt_map_type::iterator itr = list_option_dic.find(argv[pos]);
78                 if (itr != list_option_dic.end()) { // option string function find.
79                         if (! itr->second(pos, argc, argv)) {
80                                 return false; // option string function error.
81                         }
82                 } else { //option string function not found.
83                         // print option not found message.
84                         std::stringstream buf;
85                         buf << "list option not found: " << argv[pos];
86                         l7vsadm_err.setter(true, buf.str());
87                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 1, buf.str(), __FILE__, __LINE__);
88                         return false;
89                 }
90         }
91         return true;
92 }
93 //
94 // option list functions.
95 //
96 //! list numeric flag check.
97 //! @param[in] argument position
98 //! @param[in] argument count
99 //! @param[in] argument value
100 bool l7vs::l7vsadm::parse_opt_list_numeric_func(int &pos, int argc, char *argv[])
101 {
102         Logger logger(LOG_CAT_L7VSADM_COMMON, 2, "l7vsadm::parse_opt_list_numeric_func", __FILE__, __LINE__);
103
104         numeric_flag = true; //numeric flag on.
105         return true;
106 }
107
108 //! virtualservice command parsing.
109 //! @param[in] request command
110 //! @param[in] argument count
111 //! @param[in] argument value
112 bool l7vs::l7vsadm::parse_vs_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
113 {
114         Logger logger(LOG_CAT_L7VSADM_COMMON, 3, "l7vsadm::parse_vs_func", __FILE__, __LINE__);
115
116         request.command = cmd; // set command
117         if (l7vsadm_request::CMD_FLUSH_VS == cmd) {
118                 if (argc != 2) {
119                         std::stringstream buf;
120                         buf << "Argument argc is illegal for " << argv[1] << " command.";
121                         l7vsadm_err.setter(true, buf.str());
122                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 118, buf.str(), __FILE__, __LINE__);
123                         return false;
124                 }
125         } else {
126                 if (argc < 6) {
127                         std::stringstream buf;
128                         buf << "Argument argc is illegal for " << argv[1] << " command.";
129                         l7vsadm_err.setter(true, buf.str());
130                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 119, buf.str(), __FILE__, __LINE__);
131                         return false;
132                 }
133         }
134
135         std::map<std::string, int> count_map;
136
137         for (parse_opt_map_type::iterator itr = vs_option_dic.begin() ;
138              itr != vs_option_dic.end() ; ++itr) {
139                 count_map[ itr->first ] = 0;
140         }
141
142         if (l7vsadm_request::CMD_EDIT_VS == cmd) {
143                 request.vs_element.access_log_flag = -1;
144         }
145
146         for (int pos = 2; pos < argc; ++pos) { // check options.
147                 parse_opt_map_type::iterator itr = vs_option_dic.find(argv[pos]);
148                 if (itr != vs_option_dic.end()) { // find option
149                         count_map[ itr->first ]++;
150                         if (! itr->second(pos, argc, argv)) {
151                                 return false; // option function execute.
152                         }
153                 } else { // not found option function.
154                         std::stringstream buf;
155                         buf << "virtualservice option not found: " << argv[pos];
156                         l7vsadm_err.setter(true, buf.str());
157                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 2, buf.str(), __FILE__, __LINE__);
158                         return false;
159                 }
160         }
161         // check virtualservice on response
162         if (l7vsadm_request::CMD_FLUSH_VS == cmd) {
163                 // flush vs required no option
164                 return true;
165         }
166         if ((l7vsadm_request::CMD_ADD_VS == cmd) && (request.vs_element.schedule_module_name.length() == 0)) {
167                 //scheduler module not specified
168                 //scheduler module check.
169                 std::string scheduler_name = L7VSADM_DEFAULT_SCHEDULER; //default scheduler
170                 schedule_module_control &ctrl = schedule_module_control::getInstance();
171                 ctrl.initialize(L7VS_MODULE_PATH);
172                 schedule_module_base *module;
173                 try {
174                         module = ctrl.load_module(scheduler_name);
175                 } catch (...) {
176                         std::stringstream buf;
177                         buf << "scheduler module load error(--scheduler): " << scheduler_name;
178                         l7vsadm_err.setter(true, buf.str());
179                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 3, buf.str(), __FILE__, __LINE__);
180                         return false;
181                 }
182                 if (!module) {
183                         // schedule module not found
184                         std::stringstream buf;
185                         buf << "scheduler module not found(--scheduler): " << scheduler_name;
186                         l7vsadm_err.setter(true, buf.str());
187                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 4, buf.str(), __FILE__, __LINE__);
188                         return false;
189                 }
190                 ctrl.unload_module(module);
191                 request.vs_element.schedule_module_name = scheduler_name;
192         }
193         if (request.vs_element.protocol_module_name.length() == 0) {
194                 //protocol module name error
195                 std::string buf("protocol module is not specified.(--proto-module)");
196                 l7vsadm_err.setter(true, buf);
197                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 5, buf, __FILE__, __LINE__);
198                 return false;
199         }
200         if (request.vs_element.udpmode) {
201                 if (request.vs_element.udp_recv_endpoint == boost::asio::ip::udp::endpoint()) {
202                         // udp mode, but no receive endpoint
203                         std::string buf("udp recv endpoint is not specified.(--udp-service)");
204                         l7vsadm_err.setter(true, buf);
205                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 6, buf, __FILE__, __LINE__);
206                         return false;
207                 }
208         } else {
209                 if (request.vs_element.tcp_accept_endpoint == boost::asio::ip::tcp::endpoint()) {
210                         // tcp mode, but no acceptor endpoint
211                         std::string buf("tcp accpeptor endpoint is not specified.(--tcp-service)");
212                         l7vsadm_err.setter(true, buf);
213                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 7, buf, __FILE__, __LINE__);
214                         return false;
215                 }
216         }
217         if (0 > request.vs_element.sorry_maxconnection) {
218                 std::string buf("invalid sorry max connection value.(--upper)");
219                 l7vsadm_err.setter(true, buf);
220                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 8, buf, __FILE__, __LINE__);
221                 return false;
222         }
223         if ((l7vsadm_request::CMD_ADD_VS == cmd) &&
224             (request.vs_element.sorry_fwdmode == virtualservice_element::FWD_NONE)) {
225                 request.vs_element.sorry_fwdmode = virtualservice_element::FWD_MASQ;
226         }
227
228         if ((l7vsadm_request::CMD_ADD_VS == cmd) &&
229             (request.vs_element.access_log_flag == 1) && (request.vs_element.access_log_file_name.length() == 0)) {
230                 std::string buf("access log file is not specified.(--access-log-name)");
231                 l7vsadm_err.setter(true, buf);
232                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 89, buf, __FILE__, __LINE__);
233                 return false;
234         }
235
236         if (l7vsadm_request::CMD_EDIT_VS == cmd) {
237                 // Existence check of the parameter
238                 if (count_map["-s"] == 0 &&
239                     count_map["--scheduler"] == 0 &&
240                     count_map["-u"] == 0 &&
241                     count_map["--upper"] == 0 &&
242                     count_map["-b"] == 0 &&
243                     count_map["--bypass"] == 0 &&
244                     count_map["-f"] == 0 &&
245                     count_map["--flag"] == 0 &&
246                     count_map["--masq"] == 0 &&
247                     count_map["--tproxy"] == 0 &&
248                     count_map["-Q"] == 0 &&
249                     count_map["--qos-up"] == 0 &&
250                     count_map["-q"] == 0 &&
251                     count_map["--qos-down"] == 0 &&
252                     count_map["-L"] == 0 &&
253                     count_map["--access-log"] == 0) {
254
255                         std::string buf("All option omitted for edit vs command.");
256                         l7vsadm_err.setter(true, buf);
257                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 116, buf, __FILE__, __LINE__);
258                         return false;
259                 }
260         }
261
262         //conflict check
263         std::string conflict_option_name;
264         bool is_conflict = false;
265
266         for (std::map<std::string, int>::iterator itr = count_map.begin() ;
267              itr != count_map.end() ; ++itr) {
268                 if (itr->second > 1) {
269                         conflict_option_name = itr->first;
270                         is_conflict = true;
271                         break;
272                 }
273         }
274
275         if (is_conflict == false &&
276             count_map["-t"] == 1 && count_map["--tcp-service"] == 1) {
277                 //-t(--tcp-service)
278                 conflict_option_name = "--tcp-service";
279                 is_conflict = true;
280         }
281         if (is_conflict == false &&
282             count_map["-m"] == 1 && count_map["--proto-module"] == 1) {
283                 //-m(--proto-module)
284                 conflict_option_name = "--proto-module";
285                 is_conflict = true;
286         }
287         if (is_conflict == false &&
288             count_map["-s"] == 1 && count_map["--scheduler"] == 1) {
289                 //-s(--scheduler)
290                 conflict_option_name = "--scheduler";
291                 is_conflict = true;
292         }
293         if (is_conflict == false &&
294             count_map["-u"] == 1 && count_map["--upper"] == 1) {
295                 //-u(--upper)
296                 conflict_option_name = "--upper";
297                 is_conflict = true;
298         }
299         if (is_conflict == false &&
300             count_map["-b"] == 1 && count_map["--bypass"] == 1) {
301                 //-b(--bypass)
302                 conflict_option_name = "--bypass";
303                 is_conflict = true;
304         }
305         if (is_conflict == false &&
306             count_map["-f"] == 1 && count_map["--flag"] == 1) {
307                 //-f(--flag)
308                 conflict_option_name = "--flag";
309                 is_conflict = true;
310         }
311         if (is_conflict == false &&
312             count_map["--masq"] + count_map["--tproxy"] > 1) {
313                 conflict_option_name = "--masq/tproxy";
314                 is_conflict = true;
315         }
316         if (is_conflict == false &&
317             count_map["-Q"] == 1 && count_map["--qos-up"] == 1) {
318                 //-Q(--qos-up)
319                 conflict_option_name = "--qos-up";
320                 is_conflict = true;
321         }
322         if (is_conflict == false &&
323             count_map["-q"] == 1 && count_map["--qos-down"] == 1) {
324                 //-q(--qos-down)
325                 conflict_option_name = "--qos-down";
326                 is_conflict = true;
327         }
328         if (is_conflict == false &&
329             count_map["-p"] == 1 && count_map["--udp"] == 1) {
330                 //-p(--udp)
331                 conflict_option_name = "--udp";
332                 is_conflict = true;
333         }
334         if (is_conflict == false &&
335             count_map["-z"] == 1 && count_map["--ssl"] == 1) {
336                 //-z(--ssl)
337                 conflict_option_name = "--ssl";
338                 is_conflict = true;
339         }
340         if (is_conflict == false &&
341             count_map["-O"] == 1 && count_map["--sockopt"] == 1) {
342                 //-O(--sockopt)
343                 conflict_option_name = "--sockopt";
344                 is_conflict = true;
345         }
346         if (is_conflict == false &&
347             count_map["-L"] == 1 && count_map["--access-log"] == 1) {
348                 //-L(--access-log)
349                 conflict_option_name = "--access-log";
350                 is_conflict = true;
351         }
352         if (is_conflict == false &&
353             count_map["-a"] == 1 && count_map["--access-log-name"] == 1) {
354                 //-a(--access-log-name)
355                 conflict_option_name = "--access-log-name";
356                 is_conflict = true;
357         }
358
359         if (is_conflict == true) {
360                 std::stringstream buf;
361                 buf << "Option " << conflict_option_name << " is conflict.";
362                 l7vsadm_err.setter(true, buf.str());
363                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 120, buf.str(), __FILE__, __LINE__);
364                 return false;
365         }
366
367         if (l7vsadm_request::CMD_ADD_VS == cmd &&
368             (count_map["-z"] > 0 || count_map["--ssl"] > 0)) {
369                 protocol_module_control &ctrl
370                 = protocol_module_control::getInstance();
371                 ctrl.initialize(L7VS_MODULE_PATH);
372                 protocol_module_base *module;
373                 try {
374                         module
375                         = ctrl.load_module(request.vs_element.protocol_module_name);
376                 } catch (...) {
377                         std::stringstream buf;
378                         buf << "protocol module load error(--proto-module): "
379                             << request.vs_element.protocol_module_name;
380                         l7vsadm_err.setter(true, buf.str());
381                         Logger::putLogError(
382                                 LOG_CAT_L7VSADM_PARSE,
383                                 108,
384                                 buf.str(),
385                                 __FILE__,
386                                 __LINE__);
387                         return false;
388                 }
389                 if (!module) {
390                         // protocol module not found.
391                         std::stringstream buf;
392                         buf << "protocol module not found(--proto-module): "
393                             << request.vs_element.protocol_module_name;
394                         l7vsadm_err.setter(true, buf.str());
395                         Logger::putLogError(
396                                 LOG_CAT_L7VSADM_PARSE,
397                                 109, buf.str(),
398                                 __FILE__,
399                                 __LINE__);
400                         return false;
401                 }
402
403                 bool module_used_flag = module->is_exec_OK(VS_CONTACT_CLASS_SSL);
404                 if (module_used_flag == false) {
405                         // protocol module not found.
406                         std::stringstream buf;
407                         buf << "You cannot set \"-z\" option with \"sslid\" protocol module.";
408                         l7vsadm_err.setter(true, buf.str());
409                         Logger::putLogError(
410                                 LOG_CAT_L7VSADM_PARSE,
411                                 110,
412                                 buf.str(),
413                                 __FILE__,
414                                 __LINE__);
415                         return false;
416                 }
417         }
418
419         return true;
420 }
421 //
422 // option virtualservice functions.
423 //
424 //! target option check
425 //! @param[in] argument position
426 //! @param[in] argument count
427 //! @param[in] argument value
428 bool l7vs::l7vsadm::parse_opt_vs_target_func(int &pos, int argc, char *argv[])
429 {
430         Logger logger(LOG_CAT_L7VSADM_COMMON, 4, "l7vsadm::parse_opt_vs_target_func", __FILE__, __LINE__);
431
432         if (++pos >= argc) {
433                 // target address and port are not specified
434                 std::string buf("target endpoint is not specified.(--tcp-service)");
435                 l7vsadm_err.setter(true, buf);
436                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 9, buf, __FILE__, __LINE__);
437                 return false;
438         }
439         // get host endpoint from string
440         std::string src_str = argv[pos];
441         if (request.vs_element.udpmode) {
442                 error_code err;
443                 request.vs_element.udp_recv_endpoint = string_to_endpoint<boost::asio::ip::udp>(src_str, err);
444                 if (err) {
445                         std::stringstream buf;
446                         buf << "target endpoint parse error(--tcp-service): " << err.get_message() << src_str;
447                         l7vsadm_err.setter(true, buf.str());
448                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 10, buf.str(), __FILE__, __LINE__);
449                         return false;
450                 }
451                 check_endpoint<boost::asio::ip::udp>(request.vs_element.udp_recv_endpoint, true, err);
452                 if (err) {
453                         std::stringstream buf;
454                         buf << "target endpoint parse error(--tcp-service): " << err.get_message() << src_str;
455                         l7vsadm_err.setter(true, buf.str());
456                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 11, buf.str(), __FILE__, __LINE__);
457                         return false;
458                 }
459         } else {
460                 error_code err;
461                 request.vs_element.tcp_accept_endpoint = string_to_endpoint<boost::asio::ip::tcp>(src_str, err);
462                 if (err) {
463                         std::stringstream buf;
464                         buf << "target endpoint parse error(--tcp-service): " << err.get_message() << src_str;
465                         l7vsadm_err.setter(true, buf.str());
466                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 12, buf.str(), __FILE__, __LINE__);
467                         return false;
468                 }
469                 check_endpoint<boost::asio::ip::tcp>(request.vs_element.tcp_accept_endpoint, true, err);
470                 if (err) {
471                         std::stringstream buf;
472                         buf << "target endpoint parse error(--tcp-service): " << err.get_message() << src_str;
473                         l7vsadm_err.setter(true, buf.str());
474                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 13, buf.str(), __FILE__, __LINE__);
475                         return false;
476                 }
477         }
478         return true;
479 }
480 //! module option check
481 //! @param[in] argument position
482 //! @param[in] argument count
483 //! @param[in] argument value
484 bool l7vs::l7vsadm::parse_opt_vs_module_func(int &pos, int argc, char *argv[])
485 {
486         Logger logger(LOG_CAT_L7VSADM_COMMON, 5, "l7vsadm::parse_opt_vs_module_func", __FILE__, __LINE__);
487         if (++pos >= argc) {
488                 // target protomod name not specified.
489                 std::string buf("protocol module name is not specified.(--proto-module)");
490                 l7vsadm_err.setter(true, buf);
491                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 14, buf, __FILE__, __LINE__);
492                 return false;
493         }
494         std::string module_name = argv[pos];
495         if (L7VS_MODNAME_LEN < module_name.length()) {
496                 std::string buf("protocol module name is too long.(--proto-module)");
497                 l7vsadm_err.setter(true, buf);
498                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 15, buf, __FILE__, __LINE__);
499                 return false;
500         }
501         protocol_module_control &ctrl = protocol_module_control::getInstance();
502         ctrl.initialize(L7VS_MODULE_PATH);
503         protocol_module_base *module;
504         try {
505                 module = ctrl.load_module(module_name);
506         } catch (...) {
507                 std::stringstream buf;
508                 buf << "protocol module load error(--proto-module): " << module_name;
509                 l7vsadm_err.setter(true, buf.str());
510                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 16, buf.str(), __FILE__, __LINE__);
511                 return false;
512         }
513         if (!module) {
514                 // protocol module not found.
515                 std::stringstream buf;
516                 buf << "protocol module not found(--proto-module): " << module_name;
517                 l7vsadm_err.setter(true, buf.str());
518                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 17, buf.str(), __FILE__, __LINE__);
519                 return false;
520         }
521         module->init_logger_functions(
522                 boost::bind(&l7vs::Logger::getLogLevel, l7vs::LOG_CAT_PROTOCOL),
523                 boost::bind(&l7vs::Logger::putLogFatal, l7vs::LOG_CAT_PROTOCOL, _1, _2, _3, _4),
524                 boost::bind(&l7vs::Logger::putLogError, l7vs::LOG_CAT_PROTOCOL, _1, _2, _3, _4),
525                 boost::bind(&l7vs::Logger::putLogWarn, l7vs::LOG_CAT_PROTOCOL, _1, _2, _3, _4),
526                 boost::bind(&l7vs::Logger::putLogInfo, l7vs::LOG_CAT_PROTOCOL, _1, _2, _3, _4),
527                 boost::bind(&l7vs::Logger::putLogDebug, l7vs::LOG_CAT_PROTOCOL, _1, _2, _3, _4));
528         // create module args.
529         std::vector<std::string> module_args;
530         while (true) {
531                 if (++pos == argc) break; //module option end.
532                 parse_opt_map_type::iterator vsitr = vs_option_dic.find(argv[pos]);
533                 if (vsitr != vs_option_dic.end()) {
534                         --pos; // back for next option
535                         break; // module option end.
536                 }
537                 parse_opt_map_type::iterator rsitr = rs_option_dic.find(argv[pos]);
538                 if (rsitr != rs_option_dic.end()) {
539                         --pos; // back for next option
540                         break; // module option end.
541                 }
542                 module_args.push_back(argv[pos]);
543         }
544         protocol_module_base::check_message_result module_message = module->check_parameter(module_args);
545
546         if (!module_message.flag) {
547                 // args is not supported.
548                 std::stringstream buf;
549                 buf << "protocol module argument error(--proto-module): " << module_message.message;
550                 l7vsadm_err.setter(true, buf.str());
551                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 18, buf.str(), __FILE__, __LINE__);
552                 return false;
553         }
554         request.vs_element.protocol_module_name = module_name;
555         BOOST_FOREACH(std::string str, module_args) {
556                 request.vs_element.protocol_args.push_back(str);
557         }
558         ctrl.unload_module(module);
559
560         return true;
561 }
562
563 //! scheduler option check.
564 //! @param[in] argument position
565 //! @param[in] argument count
566 //! @param[in] argument value
567 bool l7vs::l7vsadm::parse_opt_vs_scheduler_func(int &pos, int argc, char *argv[])
568 {
569         Logger logger(LOG_CAT_L7VSADM_COMMON, 6, "l7vsadm::parse_opt_vs_scheduler_func", __FILE__, __LINE__);
570
571         if (++pos >= argc) {
572                 // target scheduler name not specified.
573                 std::string buf("schedule module name is not specified.(--scheduler)");
574                 l7vsadm_err.setter(true, buf);
575                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 19, buf, __FILE__, __LINE__);
576                 return false;
577         }
578         //schedule module check.
579         std::string scheduler_name = argv[pos];
580         if (L7VS_MODNAME_LEN < scheduler_name.length()) {
581                 std::string buf("schedule module name is too long.(--scheduler)");
582                 l7vsadm_err.setter(true, buf);
583                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 20, buf, __FILE__, __LINE__);
584                 return false;
585         }
586         schedule_module_control &ctrl = schedule_module_control::getInstance();
587         ctrl.initialize(L7VS_MODULE_PATH);
588         schedule_module_base *module;
589         try {
590                 module = ctrl.load_module(scheduler_name);
591         } catch (...) {
592                 std::stringstream buf;
593                 buf << "scheduler module load error(--scheduler): " << scheduler_name;
594                 l7vsadm_err.setter(true, buf.str());
595                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 21, buf.str(), __FILE__, __LINE__);
596                 return false;
597         }
598         if (!module) {
599                 // schedule module not found
600                 std::stringstream buf;
601                 buf << "scheduler module not found(--scheduler): " << scheduler_name;
602                 l7vsadm_err.setter(true, buf.str());
603                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 22, buf.str(), __FILE__, __LINE__);
604                 return false;
605         }
606         ctrl.unload_module(module);
607         request.vs_element.schedule_module_name = scheduler_name;
608         return true;
609 }
610 //! upper flag check
611 //! @param[in] argument position
612 //! @param[in] argument count
613 //! @param[in] argument value
614 bool l7vs::l7vsadm::parse_opt_vs_upper_func(int &pos, int argc, char *argv[])
615 {
616         Logger logger(LOG_CAT_L7VSADM_COMMON, 7, "l7vsadm::parse_opt_vs_upper_func", __FILE__, __LINE__);
617
618         if (++pos >= argc) {
619                 // target max connection number not specified
620                 std::string buf("sorry max connection value is not specified.(--upper)");
621                 l7vsadm_err.setter(true, buf);
622                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 23, buf, __FILE__, __LINE__);
623                 return false;
624         }
625         try {
626                 request.vs_element.sorry_maxconnection = boost::lexical_cast<long long>(argv[pos]);
627                 if ((0LL > request.vs_element.sorry_maxconnection) ||
628                     (100000LL < request.vs_element.sorry_maxconnection)) {
629                         std::string buf("invalid sorry max connection value.(--upper)");
630                         l7vsadm_err.setter(true, buf);
631                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 24, buf, __FILE__, __LINE__);
632                         return false;
633                 }
634                 if (0LL == request.vs_element.sorry_maxconnection)
635                         request.vs_element.sorry_maxconnection = LLONG_MAX; // clear value
636         } catch (boost::bad_lexical_cast &e) {
637                 std::string buf("invalid sorry max connection value.(--upper)");
638                 l7vsadm_err.setter(true, buf);
639                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 25, buf, __FILE__, __LINE__);
640                 return false;
641         }
642         //check connection limit and zero
643         return true;
644 }
645 //! bypass(SorryServer) option check
646 //! @param[in] argument position
647 //! @param[in] argument count
648 //! @param[in] argument value
649 bool l7vs::l7vsadm::parse_opt_vs_bypass_func(int &pos, int argc, char *argv[])
650 {
651         Logger logger(LOG_CAT_L7VSADM_COMMON, 8, "l7vsadm::parse_opt_vs_bypass_func", __FILE__, __LINE__);
652
653         if (++pos >= argc) {
654                 // sorryserver addr and port not specified
655                 std::string buf("sorryserver endpoint is not specified.(--bypass)");
656                 l7vsadm_err.setter(true, buf);
657                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 26, buf, __FILE__, __LINE__);
658                 return false;
659         }
660         std::string sorry_endpoint = argv[pos];
661         error_code err;
662         request.vs_element.sorry_endpoint = string_to_endpoint<boost::asio::ip::tcp>(sorry_endpoint, err);
663         if (err) {
664                 std::stringstream buf;
665                 buf << "sorryserver endpoint parse error(--bypass): " << err.get_message() << sorry_endpoint;
666                 l7vsadm_err.setter(true, buf.str());
667                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 27, buf.str(), __FILE__, __LINE__);
668                 return false;
669         }
670         // clear endpoint check (0.0.0.0:0)
671         if (request.vs_element.sorry_endpoint == boost::asio::ip::tcp::endpoint()) {
672                 request.vs_element.sorry_endpoint = boost::asio::ip::tcp::endpoint(
673                                 boost::asio::ip::address::from_string("255.255.255.255"), 0);
674         } else {
675                 check_endpoint<boost::asio::ip::tcp>(request.vs_element.sorry_endpoint, false, err);
676                 if (err) {
677                         std::stringstream buf;
678                         buf << "sorryserver endpoint parse error(--bypass): " << err.get_message() << sorry_endpoint;
679                         l7vsadm_err.setter(true, buf.str());
680                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 29, buf.str(), __FILE__, __LINE__);
681                         return false;
682                 }
683         }
684         return true;
685 }
686 //! virtualservice option flag function
687 //! @param[in] argument position
688 //! @param[in] argument count
689 //! @param[in] argument value
690 bool l7vs::l7vsadm::parse_opt_vs_flag_func(int &pos, int argc, char *argv[])
691 {
692         Logger logger(LOG_CAT_L7VSADM_COMMON, 9, "l7vsadm::parse_opt_vs_flag_func", __FILE__, __LINE__);
693
694         if (++pos >= argc) {
695                 // sorry flag is not specified
696                 std::string buf("sorry flag value is not specified.(--flag)");
697                 l7vsadm_err.setter(true, buf);
698                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 30, buf, __FILE__, __LINE__);
699                 return false;
700         }
701         try {
702                 int tmp = boost::lexical_cast<int>(argv[pos]);
703                 if ((0 != tmp) && (1 != tmp)) {
704                         std::string buf("invalid sorry flag value.(--flag)");
705                         l7vsadm_err.setter(true, buf);
706                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 31, buf, __FILE__, __LINE__);
707                         return false;
708                 }
709                 if (0 == tmp)
710                         request.vs_element.sorry_flag = INT_MAX; // clear value
711                 else
712                         request.vs_element.sorry_flag = 1;
713         } catch (boost::bad_lexical_cast &e) {
714                 std::string buf("invalid sorry flag value.(--flag)");
715                 l7vsadm_err.setter(true, buf);
716                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 32, buf, __FILE__, __LINE__);
717                 return false;
718         }
719         return true;
720 }
721 //! virtualservice option sorry forward mode function
722 //! @param[in] argument position
723 //! @param[in] argument count
724 //! @param[in] argument value
725 bool l7vs::l7vsadm::parse_opt_vs_fwdmode_func(int &pos, int argc, char *argv[])
726 {
727         Logger logger(LOG_CAT_L7VSADM_COMMON, /*XXX*/999, "l7vsadm::parse_opt_vs_fwdmode_func", __FILE__, __LINE__);
728
729         std::string opt(argv[pos]);
730         if (opt == "--masq") {
731                 request.vs_element.sorry_fwdmode = virtualservice_element::FWD_MASQ;
732         } else if (opt == "--tproxy") {
733 #ifdef IP_TRANSPARENT
734                 request.vs_element.sorry_fwdmode = virtualservice_element::FWD_TPROXY;
735 #else
736                 std::stringstream buf("tproxy(IP_TRANSPARENT) not supported on this platform.");
737                 l7vsadm_err.setter(true, buf.str());
738                 Logger::putLogInfo(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
739                 return false;
740 #endif
741         } else {
742                 // should never come here
743                 std::stringstream buf;
744                 buf << boost::format("unknown sorryserver forward mode specified.(%s)") % opt;
745                 l7vsadm_err.setter(true, buf.str());
746                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
747                 return false;
748         }
749         return true;
750 }
751 //! virtualservice option qosupstream function
752 //! @param[in] argument position
753 //! @param[in] argument count
754 //! @param[in] argument value
755 bool l7vs::l7vsadm::parse_opt_vs_qosup_func(int &pos, int argc, char *argv[])
756 {
757         Logger logger(LOG_CAT_L7VSADM_COMMON, 10, "l7vsadm::parse_opt_vs_qosup_func", __FILE__, __LINE__);
758
759         if (++pos >= argc) {
760                 // QoS upstream value is not specified.
761                 std::string buf("QoS upstream value is not specified.(--qos-up)");
762                 l7vsadm_err.setter(true, buf);
763                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 33, buf, __FILE__, __LINE__);
764                 return false;
765         }
766         try {
767                 virtualservice_element &elem = request.vs_element; // request virtualservice element reference get.
768                 std::string tmp = argv[pos];
769                 std::string::reverse_iterator ritr = tmp.rbegin();
770                 if (*ritr == 'G' || *ritr == 'g') {
771                         std::string strval = tmp.substr(0, tmp.length() - 1);
772                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
773                         if (ullval > 999) {
774                                 std::string buf("QoS upstream value is too big.(--qos-up)");
775                                 l7vsadm_err.setter(true, buf);
776                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 34, buf, __FILE__, __LINE__);
777                                 return false;
778                         }
779                         elem.qos_upstream = ullval * 1000 * 1000 * 1000; // set qos_upstream
780                 } else if (*ritr == 'M' || *ritr == 'm') {
781                         std::string strval = tmp.substr(0, tmp.length() - 1);
782                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
783                         if (ullval > 999) {
784                                 std::string buf("QoS upstream value is too big.(--qos-up)");
785                                 l7vsadm_err.setter(true, buf);
786                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 35, buf, __FILE__, __LINE__);
787                                 return false;
788                         }
789                         elem.qos_upstream = ullval * 1000 * 1000; // set qos_upstream
790                 } else if (*ritr == 'K' || *ritr == 'k') {
791                         std::string strval = tmp.substr(0, tmp.length() - 1);
792                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
793                         if (ullval > 999) {
794                                 std::string buf("QoS upstream value is too big.(--qos-up)");
795                                 l7vsadm_err.setter(true, buf);
796                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 36, buf, __FILE__, __LINE__);
797                                 return false;
798                         }
799                         elem.qos_upstream = ullval * 1000; // set qos_upstream
800                 } else {
801                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (argv[pos]);
802                         if (ullval > 999) {
803                                 std::string buf("QoS upstream value is too big.(--qos-up)");
804                                 l7vsadm_err.setter(true, buf);
805                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 111, buf, __FILE__, __LINE__);
806                                 return false;
807                         }
808                         elem.qos_upstream = ullval; // set qos_upstream
809                 }
810                 if (0ULL == elem.qos_upstream) {
811                         elem.qos_upstream = ULLONG_MAX; // clear value
812                 } else {
813                         elem.qos_upstream /= 8; //qos convert to bytes per sec to bit per sec
814                 }
815
816         } catch (boost::bad_lexical_cast &ex) {
817                 std::string buf("invalid QoS upstream value.(--qos-up)");
818                 l7vsadm_err.setter(true, buf);
819                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 37, buf, __FILE__, __LINE__);
820                 return false;
821         }
822         return true;
823 }
824 //! virtualservice option qosdownstream function
825 //! @param[in] argument position
826 //! @param[in] argument count
827 //! @param[in] argument value
828 bool l7vs::l7vsadm::parse_opt_vs_qosdown_func(int &pos, int argc, char *argv[])
829 {
830         Logger logger(LOG_CAT_L7VSADM_COMMON, 11, "l7vsadm::parse_opt_vs_qosdown_func", __FILE__, __LINE__);
831
832         if (++pos >= argc) {
833                 // QoS downstream value is not specified
834                 std::string buf("QoS downstream value is not specified.(--qos-down)");
835                 l7vsadm_err.setter(true, buf);
836                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 38, buf, __FILE__, __LINE__);
837                 return false;
838         }
839         try {
840                 virtualservice_element &elem = request.vs_element; // request virtualservice element reference get.
841                 std::string tmp = argv[pos];
842                 std::string::reverse_iterator ritr = tmp.rbegin();
843                 if (*ritr == 'G' || *ritr == 'g') {
844                         std::string strval = tmp.substr(0, tmp.length() - 1);
845                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
846                         if (ullval > 999) {
847                                 std::string buf("QoS downstream value is too big.(--qos-down)");
848                                 l7vsadm_err.setter(true, buf);
849                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 39, buf, __FILE__, __LINE__);
850                                 return false;
851                         }
852                         elem.qos_downstream = ullval * 1000 * 1000 * 1000; // set qos_upstream
853                 } else if (*ritr == 'M' || *ritr == 'm') {
854                         std::string strval = tmp.substr(0, tmp.length() - 1);
855                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
856                         if (ullval > 999) {
857                                 std::string buf("QoS downstream value is too big.(--qos-down)");
858                                 l7vsadm_err.setter(true, buf);
859                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 40, buf, __FILE__, __LINE__);
860                                 return false;
861                         }
862                         elem.qos_downstream = ullval * 1000 * 1000; // set qos_upstream
863                 } else if (*ritr == 'K' || *ritr == 'k') {
864                         std::string strval = tmp.substr(0, tmp.length() - 1);
865                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (strval);
866                         if (ullval > 999) {
867                                 std::string buf("QoS downstream value is too big.(--qos-down)");
868                                 l7vsadm_err.setter(true, buf);
869                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 41, buf, __FILE__, __LINE__);
870                                 return false;
871                         }
872                         elem.qos_downstream = ullval * 1000; // set qos_upstream
873                 } else {
874                         unsigned long long ullval = boost::lexical_cast<unsigned long long> (argv[pos]);
875                         if (ullval > 999) {
876                                 std::string buf("QoS downstream value is too big.(--qos-down)");
877                                 l7vsadm_err.setter(true, buf);
878                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 115, buf, __FILE__, __LINE__);
879                                 return false;
880                         }
881                         elem.qos_downstream = boost::lexical_cast<unsigned long long> (argv[pos]); // set qos_downstream
882                 }
883                 if (0ULL == elem.qos_downstream) {
884                         elem.qos_downstream = ULLONG_MAX; // clear value
885                 } else {
886                         elem.qos_downstream /= 8; //qos convert to bytes per sec to bit per sec
887                 }
888         } catch (boost::bad_lexical_cast &ex) {
889                 // don' conv qos downstream
890                 std::string buf("invalid QoS downstream value.(--qos-down)");
891                 l7vsadm_err.setter(true, buf);
892                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 42, buf, __FILE__, __LINE__);
893                 return false;
894         }
895         return true;
896 }
897 //! virtualservice option udp func.
898 //! @param[in] argument position
899 //! @param[in] argument count
900 //! @param[in] argument value
901 bool l7vs::l7vsadm::parse_opt_vs_udp_func(int &pos, int argc, char *argv[])
902 {
903         Logger logger(LOG_CAT_L7VSADM_COMMON, 12, "l7vsadm::parse_opt_vs_udp_func", __FILE__, __LINE__);
904
905         virtualservice_element &elem = request.vs_element; // request virtualservice element reference get.
906         elem.udpmode = true; // udpmode on.
907         boost::asio::ip::tcp::endpoint zeropoint;
908         if (zeropoint != elem.tcp_accept_endpoint) { // address tcp_acceptor endpoint
909                 std::stringstream sstream;
910                 sstream << elem.tcp_accept_endpoint;
911                 std::string endpoint = sstream.str();
912                 error_code err;
913                 elem.udp_recv_endpoint = string_to_endpoint<boost::asio::ip::udp>(endpoint, err);
914                 if (err) {
915                         std::stringstream buf;
916                         buf << "target endpoint parse error(--udp-service): " << err.get_message() << endpoint;
917                         l7vsadm_err.setter(true, buf.str());
918                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 43, buf.str(), __FILE__, __LINE__);
919                         return false;
920                 }
921                 elem.tcp_accept_endpoint = zeropoint;
922         }
923         if (elem.realserver_vector.size() != 0 && elem.realserver_vector.front().tcp_endpoint != zeropoint) {
924                 std::stringstream sstream;
925                 sstream << elem.realserver_vector.front().tcp_endpoint;
926                 std::string endpoint = sstream.str();
927                 error_code err;
928                 elem.realserver_vector.front().udp_endpoint = string_to_endpoint<boost::asio::ip::udp> (endpoint, err);
929                 if (err) {
930                         std::stringstream buf;
931                         buf << "realserver endpoint parse error(--udp-service): " << err.get_message() << endpoint;
932                         l7vsadm_err.setter(true, buf.str());
933                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 44, buf.str(), __FILE__, __LINE__);
934                         return false;
935                 }
936                 elem.realserver_vector.front().tcp_endpoint = zeropoint;
937         }
938         return true;
939 }
940 //! virtualservice option ssl_file function
941 //! @param[in] argument position
942 //! @param[in] argument count
943 //! @param[in] argument value
944 bool l7vs::l7vsadm::parse_opt_vs_ssl_file_func(int &pos, int argc, char *argv[])
945 {
946         Logger logger(LOG_CAT_L7VSADM_COMMON, 38, "l7vsadm::parse_opt_vs_ssl_file_func", __FILE__, __LINE__);
947
948         if (++pos >= argc) {
949                 std::string buf("ssl config file is not specified.(--ssl)");
950                 l7vsadm_err.setter(true, buf);
951                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 90, buf, __FILE__, __LINE__);
952                 return false;
953         }
954         // ssl config file check.
955         std::string conf_file_name = argv[pos];
956         if (L7VS_FILENAME_LEN < conf_file_name.length()) {
957                 std::string buf("ssl config file name is too long.(--ssl)");
958                 l7vsadm_err.setter(true, buf);
959                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 91, buf, __FILE__, __LINE__);
960                 return false;
961         }
962         FILE *fp;
963         if ((fp = fopen(conf_file_name.c_str(), "r")) == NULL) {
964                 std::string buf("ssl config file cannot open.(--ssl)");
965                 l7vsadm_err.setter(true, buf);
966                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 92, buf, __FILE__, __LINE__);
967                 return false;
968         }
969         fclose(fp);
970
971         request.vs_element.ssl_file_name = conf_file_name;
972         return true;
973 }
974
975 //! virtualservice option access log function
976 //! @param[in] argument position
977 //! @param[in] argument count
978 //! @param[in] argument value
979 bool l7vs::l7vsadm::parse_opt_vs_access_log_func(int &pos, int argc, char *argv[])
980 {
981         Logger logger(LOG_CAT_L7VSADM_COMMON, 39, "l7vsadm::parse_opt_vs_access_log_func", __FILE__, __LINE__);
982
983         if (++pos >= argc) {
984                 // access log flag is not specified
985                 std::string buf("access log flag value is not specified.(--access-log)");
986                 l7vsadm_err.setter(true, buf);
987                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 93, buf, __FILE__, __LINE__);
988                 return false;
989         }
990         try {
991                 int tmp = boost::lexical_cast<int>(argv[pos]);
992                 if ((0 != tmp) && (1 != tmp)) {
993                         std::string buf("invalid access log flag value.(--access-log)");
994                         l7vsadm_err.setter(true, buf);
995                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 94, buf, __FILE__, __LINE__);
996                         return false;
997                 }
998                 request.vs_element.access_log_flag = tmp;
999         } catch (boost::bad_lexical_cast &e) {
1000                 std::string buf("invalid access log flag value.(--access-log)");
1001                 l7vsadm_err.setter(true, buf);
1002                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 95, buf, __FILE__, __LINE__);
1003                 return false;
1004         }
1005         return true;
1006 }
1007
1008 //! virtualservice option access_log_logrotate function
1009 //! @param[in] argument position
1010 //! @param[in] argument count
1011 //! @param[in] argument value
1012 bool l7vs::l7vsadm::parse_opt_vs_access_log_logrotate_func(int &pos, int argc, char *argv[])
1013 {
1014         Logger logger(LOG_CAT_L7VSADM_COMMON, 40, "l7vsadm::parse_opt_vs_accesslog_logrotate_func", __FILE__, __LINE__);
1015
1016         if (++pos >= argc) {
1017                 std::string buf("access log file is not specified.(--access-log-name)");
1018                 l7vsadm_err.setter(true, buf);
1019                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 96, buf, __FILE__, __LINE__);
1020                 return false;
1021         }
1022         // access log file check.
1023         std::string access_log_file_name = argv[pos];
1024         if (L7VS_FILENAME_LEN < access_log_file_name.length()) {
1025                 std::string buf("access log file name is too long.(--access-log-name)");
1026                 l7vsadm_err.setter(true, buf);
1027                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 97, buf, __FILE__, __LINE__);
1028                 return false;
1029         }
1030         if ("/" != access_log_file_name.substr(0, 1)) {
1031                 std::string buf("please specify access log filename in fullpath.(--access-log-name)");
1032                 l7vsadm_err.setter(true, buf);
1033                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 98, buf, __FILE__, __LINE__);
1034                 return false;
1035         }
1036
1037         request.vs_element.access_log_rotate_key_info = "";
1038
1039         // create access log args.
1040         std::vector<std::string> arguments_vector;
1041         virtualservice_element::access_log_rotate_arguments_map_type arguments_map;
1042         while (true) {
1043                 if (++pos == argc) break; //access log arguments end.
1044                 parse_opt_map_type::iterator vsitr = vs_option_dic.find(argv[pos]);
1045                 if (vsitr != vs_option_dic.end()) {
1046                         --pos; // back for next option
1047                         break; // module option end.
1048                 }
1049                 arguments_vector.push_back(argv[pos]);
1050
1051                 request.vs_element.access_log_rotate_key_info += argv[pos];
1052                 request.vs_element.access_log_rotate_key_info += " ";
1053
1054         }
1055         boost::algorithm::erase_last(request.vs_element.access_log_rotate_key_info , " ");
1056
1057         if (0 < arguments_vector.size()) {
1058                 if (0 == (arguments_vector.size() % 2)) {
1059                         for (unsigned int i = 0; i < (arguments_vector.size() - 1); ++i) {
1060                                 std::pair<virtualservice_element::access_log_rotate_arguments_map_type::iterator, bool> ret =
1061                                         arguments_map.insert(
1062                                                 virtualservice_element::access_log_rotate_arguments_pair_type(
1063                                                         arguments_vector[i], arguments_vector[i+1]));
1064                                 if (!ret.second) {
1065                                         std::string buf("access log rotation argument is duplicated.(--access-log-name)");
1066                                         l7vsadm_err.setter(true, buf);
1067                                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 99, buf, __FILE__, __LINE__);
1068                                         return false;
1069                                 }
1070                                 ++i;
1071                         }
1072                 } else {
1073                         std::string buf("access log rotation argument error.(--access-log-name)");
1074                         l7vsadm_err.setter(true, buf);
1075                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 100, buf, __FILE__, __LINE__);
1076                         return false;
1077                 }
1078                 bool ret = logger_access_manager::getInstance().access_log_logrotate_parameter_check(arguments_map);
1079                 if (!ret) {
1080                         std::string buf("access log rotation argument error.(--access-log-name)");
1081                         l7vsadm_err.setter(true, buf);
1082                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 101, buf, __FILE__, __LINE__);
1083                         return false;
1084                 }
1085         }
1086
1087         request.vs_element.access_log_file_name = access_log_file_name;
1088         request.vs_element.access_log_rotate_arguments.clear();
1089         BOOST_FOREACH(virtualservice_element::access_log_rotate_arguments_pair_type pair, arguments_map) {
1090                 request.vs_element.access_log_rotate_arguments.insert(pair);
1091         }
1092
1093         return true;
1094 }
1095
1096 //! virtualservice option socket function
1097 //! @param[in] argument position
1098 //! @param[in] argument count
1099 //! @param[in] argument value
1100 bool l7vs::l7vsadm::parse_opt_vs_socket_func(int &pos, int argc, char *argv[])
1101 {
1102         Logger logger(LOG_CAT_L7VSADM_COMMON, 41, "l7vsadm::parse_opt_vs_socket_func", __FILE__, __LINE__);
1103
1104         if (++pos >= argc) {
1105                 std::string buf("socket option is not specified.(--sockopt)");
1106                 l7vsadm_err.setter(true, buf);
1107                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 102, buf, __FILE__, __LINE__);
1108                 return false;
1109         }
1110
1111         bool is_set_defer_accept = false;
1112         bool is_set_nodelay = false;
1113         bool is_set_cork = false;
1114         bool is_set_quickack = false;
1115
1116         request.vs_element.socket_option_tcp_defer_accept = 0;
1117         request.vs_element.socket_option_tcp_nodelay = 0;
1118         request.vs_element.socket_option_tcp_cork = 0;
1119         request.vs_element.socket_option_tcp_quickack = 0;
1120
1121         std::string socket_option_string = argv[pos];
1122         std::vector<std::string> socket_options;
1123         boost::split(socket_options, socket_option_string, boost::algorithm::is_any_of(","));
1124
1125         BOOST_FOREACH(std::string option, socket_options) {
1126                 if (option == "deferaccept") {
1127                         if (!is_set_defer_accept) {
1128                                 is_set_defer_accept = true;
1129                                 request.vs_element.socket_option_tcp_defer_accept = 1;
1130                         } else {
1131                                 // defer_accept is duplicated
1132                                 std::stringstream buf;
1133                                 buf << "socket option deferaccept is duplicated.(--sockopt)";
1134                                 l7vsadm_err.setter(true, buf.str());
1135                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 103, buf.str(), __FILE__, __LINE__);
1136                                 return false;
1137                         }
1138                 } else if (option == "nodelay") {
1139                         if (!is_set_nodelay) {
1140                                 is_set_nodelay = true;
1141                                 request.vs_element.socket_option_tcp_nodelay = 1;
1142                         } else {
1143                                 // nodelay is duplicated
1144                                 std::stringstream buf;
1145                                 buf << "socket option nodelay is duplicated.(--sockopt)";
1146                                 l7vsadm_err.setter(true, buf.str());
1147                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 104, buf.str(), __FILE__, __LINE__);
1148                                 return false;
1149                         }
1150                 } else if (option == "cork") {
1151                         if (!is_set_cork) {
1152                                 is_set_cork = true;
1153                                 request.vs_element.socket_option_tcp_cork = 1;
1154                         } else {
1155                                 // cork is duplicated
1156                                 std::stringstream buf;
1157                                 buf << "socket option cork is duplicated.(--sockopt)";
1158                                 l7vsadm_err.setter(true, buf.str());
1159                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 105, buf.str(), __FILE__, __LINE__);
1160                                 return false;
1161                         }
1162                 } else if (option == "quickackon" || option == "quickackoff") {
1163                         if (!is_set_quickack) {
1164                                 is_set_quickack = true;
1165                                 request.vs_element.socket_option_tcp_quickack = ((option == "quickackon") ? 1 : 2);
1166                         } else {
1167                                 // quickack is duplicated
1168                                 std::stringstream buf;
1169                                 buf << "socket option quickack is duplicated.(--sockopt)";
1170                                 l7vsadm_err.setter(true, buf.str());
1171                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 106, buf.str(), __FILE__, __LINE__);
1172                                 return false;
1173                         }
1174                 } else {
1175                         // unknown socket option
1176                         std::stringstream buf;
1177                         buf << "unknown socket option.(--sockopt)";
1178                         l7vsadm_err.setter(true, buf.str());
1179                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 107, buf.str(), __FILE__, __LINE__);
1180                         return false;
1181                 }
1182         }
1183
1184         request.vs_element.socket_option_string = socket_option_string;
1185         return true;
1186
1187 }
1188 //! realserver command parsing.
1189 //! @param[in] request command
1190 //! @param[in] argument count
1191 //! @param[in] argument value
1192 bool l7vs::l7vsadm::parse_rs_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
1193 {
1194         Logger logger(LOG_CAT_L7VSADM_COMMON, 13, "l7vsadm::parse_rs_func", __FILE__, __LINE__);
1195
1196         if (argc < 8) {
1197                 //argument num err
1198                 std::stringstream buf;
1199                 buf << "Argument argc is illegal for ";
1200                 buf << argv[1];
1201                 buf << " command.";
1202
1203                 l7vsadm_err.setter(true, buf.str());
1204                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 121, buf.str(), __FILE__, __LINE__);
1205                 return false;
1206         }
1207
1208         request.command = cmd;
1209
1210         request.vs_element.realserver_vector.push_back(realserver_element());
1211
1212         std::map<std::string, int> count_map;
1213         for (parse_opt_map_type::iterator itr = rs_option_dic.begin() ;
1214              itr != rs_option_dic.end() ; ++itr) {
1215                 count_map[ itr->first ] = 0;
1216         }
1217
1218         for (int pos = 2; pos < argc; ++pos) {
1219                 parse_opt_map_type::iterator itr = rs_option_dic.find(argv[pos]);
1220                 if (itr != rs_option_dic.end()) {
1221                         count_map[ itr->first ]++;
1222                         if (! itr->second(pos, argc, argv)) return false;
1223                 } else {
1224                         std::stringstream buf;
1225                         buf << "realserver option not found(--real-server): " << argv[pos];
1226                         l7vsadm_err.setter(true, buf.str());
1227                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 45, buf.str(), __FILE__, __LINE__);
1228                         return false;
1229                 }
1230         }
1231
1232         if (request.vs_element.protocol_module_name.length() == 0) {
1233                 //protocol module name error
1234                 std::string buf("protocol module is not specified.(--proto-module)");
1235                 l7vsadm_err.setter(true, buf);
1236                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 46, buf, __FILE__, __LINE__);
1237                 return false;
1238         }
1239         if (request.vs_element.udpmode) {
1240                 if (request.vs_element.udp_recv_endpoint == boost::asio::ip::udp::endpoint()) {
1241                         // udp mode,but not acceptor endpoint
1242                         std::string buf("udp receive endpoint is not specified.(--udp-service)");
1243                         l7vsadm_err.setter(true, buf);
1244                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 47, buf, __FILE__, __LINE__);
1245                         return false;
1246                 }
1247                 if (request.vs_element.realserver_vector.front().udp_endpoint == boost::asio::ip::udp::endpoint()) {
1248                         // udp mode,but not realserver endpoint
1249                         std::string buf("realserver udp endpoint is not specified.(--real-server)");
1250                         l7vsadm_err.setter(true, buf);
1251                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 48, buf, __FILE__, __LINE__);
1252                         return false;
1253                 }
1254         } else {
1255                 if (request.vs_element.tcp_accept_endpoint == boost::asio::ip::tcp::endpoint()) {
1256                         // tcp mode, but not acceptor endpoint
1257                         std::string buf("tcp accpeptor endpoint not specified.(--tcp-service)");
1258                         l7vsadm_err.setter(true, buf);
1259                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 49, buf, __FILE__, __LINE__);
1260                         return false;
1261                 }
1262                 if (request.vs_element.realserver_vector.front().tcp_endpoint == boost::asio::ip::tcp::endpoint()) {
1263                         // tcp mode,but not realserver endpoint
1264                         std::string buf("realserver tcp endpoint not specified.(--real-server)");
1265                         l7vsadm_err.setter(true, buf);
1266                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 50, buf, __FILE__, __LINE__);
1267                         return false;
1268                 }
1269         }
1270
1271         if (l7vsadm_request::CMD_EDIT_RS != cmd) {
1272                 // realserver weight default value = 1
1273                 if (-1 == request.vs_element.realserver_vector.front().weight) {
1274                         request.vs_element.realserver_vector.front().weight = 1;
1275                 }
1276                 // realserver forward mode default value = FWD_MASQ
1277                 if (realserver_element::FWD_NONE == request.vs_element.realserver_vector.front().fwdmode) {
1278                         request.vs_element.realserver_vector.front().fwdmode = realserver_element::FWD_MASQ;
1279                 }
1280         } else {
1281                 // Existence check of the parameter
1282                 if (count_map["-w"] == 0 &&
1283                     count_map["--weight"] == 0 &&
1284                     count_map["--masq"] == 0 &&
1285                     count_map["--tproxy"] == 0) {
1286                         std::string buf("All option omitted for edit rs command.");
1287                         l7vsadm_err.setter(true, buf);
1288                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 112, buf, __FILE__, __LINE__);
1289                         return false;
1290                 }
1291         }
1292
1293         //conflict check
1294         std::string conflict_option_name;
1295         bool is_conflict = false;
1296
1297         for (std::map<std::string, int>::iterator itr = count_map.begin() ;
1298              itr != count_map.end() ; ++itr) {
1299                 if (itr->second > 1) {
1300                         conflict_option_name = itr->first;
1301                         is_conflict = true;
1302                         break;
1303                 }
1304         }
1305
1306         if (is_conflict == false &&
1307             count_map["-t"] == 1 && count_map["--tcp-service"] == 1) {
1308                 //-t(--tcp-service)
1309                 conflict_option_name = "--tcp-service";
1310                 is_conflict = true;
1311         }
1312         if (is_conflict == false &&
1313             count_map["-m"] == 1 && count_map["--proto-module"] == 1) {
1314                 //-m(--proto-module)
1315                 conflict_option_name = "--proto-module";
1316                 is_conflict = true;
1317         }
1318         if (is_conflict == false &&
1319             count_map["-r"] == 1 && count_map["--real-server"] == 1) {
1320                 //-r(--real-server)
1321                 conflict_option_name = "--real-server";
1322                 is_conflict = true;
1323         }
1324         if ((is_conflict == false) &&
1325             (count_map["-w"] == 1) && (count_map["--weight"] == 1) &&
1326             (l7vsadm_request::CMD_DEL_RS != cmd)) {
1327                 //-w(--weight)
1328                 conflict_option_name = "--weight";
1329                 is_conflict = true;
1330         }
1331         if ((is_conflict == false) &&
1332             count_map["--masq"] + count_map["--tproxy"] > 1 &&
1333             (l7vsadm_request::CMD_DEL_RS != cmd)) {
1334                 //--masq/tproxy
1335                 conflict_option_name = "--masq/tproxy";
1336                 is_conflict = true;
1337         }
1338
1339         if (is_conflict == true) {
1340                 std::stringstream buf;
1341                 buf << "Option " << conflict_option_name << " is conflict.";
1342                 l7vsadm_err.setter(true, buf.str());
1343                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 122, buf.str(), __FILE__, __LINE__);
1344                 return false;
1345         }
1346
1347         return true;
1348 }
1349 //
1350 // realserver option functions.
1351 //
1352 //! realserver weight set
1353 //! @param[in] argument position
1354 //! @param[in] argument count
1355 //! @param[in] argument value
1356 bool l7vs::l7vsadm::parse_opt_rs_weight_func(int &pos, int argc, char *argv[])
1357 {
1358         Logger logger(LOG_CAT_L7VSADM_COMMON, 14, "l7vsadm::parse_opt_rs_weight_func", __FILE__, __LINE__);
1359
1360         if (++pos >= argc) {
1361                 // weight value is not specified
1362                 std::string buf("weight value is not specified.(--weight)");
1363                 l7vsadm_err.setter(true, buf);
1364                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 51, buf, __FILE__, __LINE__);
1365                 return false;
1366         }
1367         try {
1368                 request.vs_element.realserver_vector.front().weight = boost::lexical_cast<int>(argv[pos]);
1369                 if ((0 > request.vs_element.realserver_vector.front().weight) ||
1370                     (100 < request.vs_element.realserver_vector.front().weight)) {
1371                         std::string buf("invalid weight value.(--weight)");
1372                         l7vsadm_err.setter(true, buf);
1373                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 52, buf, __FILE__, __LINE__);
1374                         return false;
1375                 }
1376         } catch (boost::bad_lexical_cast &ex) {
1377                 // lexical cast error
1378                 std::string buf("invalid weight value.(--weight)");
1379                 l7vsadm_err.setter(true, buf);
1380                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 53, buf, __FILE__, __LINE__);
1381                 return false;
1382         }
1383         return true;
1384 }
1385 //! realserver forward mode set
1386 //! @param[in] argument position
1387 //! @param[in] argument count
1388 //! @param[in] argument value
1389 bool l7vs::l7vsadm::parse_opt_rs_fwdmode_func(int &pos, int argc, char *argv[])
1390 {
1391         Logger logger(LOG_CAT_L7VSADM_COMMON, /*XXX*/999, "l7vsadm::parse_opt_rs_fwdmode_func", __FILE__, __LINE__);
1392
1393         std::string opt(argv[pos]);
1394         if (opt == "--masq") {
1395                 request.vs_element.realserver_vector.front().fwdmode = realserver_element::FWD_MASQ;
1396         } else if (opt == "--tproxy") {
1397 #ifdef IP_TRANSPARENT
1398                 request.vs_element.realserver_vector.front().fwdmode = realserver_element::FWD_TPROXY;
1399 #else
1400                 std::stringstream buf("tproxy(IP_TRANSPARENT) not supported on this platform.");
1401                 l7vsadm_err.setter(true, buf.str());
1402                 Logger::putLogInfo(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
1403                 return false;
1404 #endif
1405         } else {
1406                 // should never come here
1407                 std::stringstream buf;
1408                 buf << boost::format("unknown realserver forward mode specified.(%s)") % opt;
1409                 l7vsadm_err.setter(true, buf.str());
1410                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, /*XXX*/999, buf.str(), __FILE__, __LINE__);
1411                 return false;
1412         }
1413         return true;
1414
1415 }
1416 //! realserver target set
1417 //! @param[in] argument position
1418 //! @param[in] argument count
1419 //! @param[in] argument value
1420 bool l7vs::l7vsadm::parse_opt_rs_realserver_func(int &pos, int argc, char *argv[])
1421 {
1422         Logger logger(LOG_CAT_L7VSADM_COMMON, 15, "l7vsadm::parse_opt_rs_realserver_func", __FILE__, __LINE__);
1423
1424         if (++pos >= argc) {
1425                 // realserver address is not specified
1426                 std::string buf("realserver address is not specified.(--real-server)");
1427                 l7vsadm_err.setter(true, buf);
1428                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 54, buf, __FILE__, __LINE__);
1429                 return false;
1430         }
1431         std::string src_str = argv[pos];
1432         if (request.vs_element.udpmode) {
1433                 error_code err;
1434                 request.vs_element.realserver_vector.front().udp_endpoint = string_to_endpoint<boost::asio::ip::udp>(src_str, err);
1435                 if (err) {
1436                         // address string error.
1437                         std::stringstream buf;
1438                         buf << "realserver endpoint parse error(--real-server): " << err.get_message() << src_str;
1439                         l7vsadm_err.setter(true, buf.str());
1440                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 55, buf.str(), __FILE__, __LINE__);
1441                         return false;
1442                 }
1443                 check_endpoint<boost::asio::ip::udp>(request.vs_element.realserver_vector.front().udp_endpoint, false, err);
1444                 if (err) {
1445                         std::stringstream buf;
1446                         buf << "realserver endpoint parse error(--real-server): " << err.get_message() << src_str;
1447                         l7vsadm_err.setter(true, buf.str());
1448                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 56, buf.str(), __FILE__, __LINE__);
1449                         return false;
1450                 }
1451         } else {
1452                 error_code err;
1453                 request.vs_element.realserver_vector.front().tcp_endpoint = string_to_endpoint<boost::asio::ip::tcp>(src_str, err);
1454                 if (err) {
1455                         // address string error.
1456                         std::stringstream buf;
1457                         buf << "realserver endpoint parse error(--real-server): " << err.get_message() << src_str;
1458                         l7vsadm_err.setter(true, buf.str());
1459                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 57, buf.str(), __FILE__, __LINE__);
1460                         return false;
1461                 }
1462                 check_endpoint<boost::asio::ip::tcp>(request.vs_element.realserver_vector.front().tcp_endpoint, false, err);
1463                 if (err) {
1464                         std::stringstream buf;
1465                         buf << "realserver endpoint parse error(--real-server): " << err.get_message() << src_str;
1466                         l7vsadm_err.setter(true, buf.str());
1467                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 58, buf.str(), __FILE__, __LINE__);
1468                         return false;
1469                 }
1470         }
1471         return true;
1472 }
1473
1474 //! replication command parsing.
1475 //! @param[in] request command
1476 //! @param[in] argument count
1477 //! @param[in] argument value
1478 bool l7vs::l7vsadm::parse_replication_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
1479 {
1480         Logger logger(LOG_CAT_L7VSADM_COMMON, 16, "l7vsadm::parse_replication_func", __FILE__, __LINE__);
1481
1482         if (argc < 3 || argc > 4) {
1483                 //argument num err
1484                 std::stringstream buf;
1485                 buf << "Argument argc is illegal for ";
1486                 buf << argv[1];
1487                 buf << " command.";
1488
1489                 l7vsadm_err.setter(true, buf.str());
1490                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 123, buf.str(), __FILE__, __LINE__);
1491                 return false;
1492         }
1493
1494         request.command = cmd;
1495
1496         for (int pos = 2; pos < argc; ++pos) {
1497                 parse_opt_map_type::iterator itr = replication_option_dic.find(argv[pos]);
1498                 if (itr != replication_option_dic.end()) {
1499                         if (! itr->second(pos, argc, argv)) return false;
1500                 } else {
1501                         std::stringstream buf;
1502                         buf << "replication option not found(--replication): " << argv[pos];
1503                         l7vsadm_err.setter(true, buf.str());
1504                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 59, buf.str(), __FILE__, __LINE__);
1505                         return false;
1506                 }
1507         }
1508         if (l7vsadm_request::REP_NONE == request.replication_command) {
1509                 // not specified replication command
1510                 std::string buf("replication command not specified.(--replication)");
1511                 l7vsadm_err.setter(true, buf);
1512                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 60, buf, __FILE__, __LINE__);
1513                 return false;
1514         }
1515
1516         return true;
1517 }
1518
1519 //
1520 // replication option functions.
1521 //
1522 //! replication switch function
1523 //! @param[in] argument position
1524 //! @param[in] argument count
1525 //! @param[in] argument value
1526 bool l7vs::l7vsadm::parse_opt_replication_switch_func(int &pos, int argc, char *argv[])
1527 {
1528         Logger logger(LOG_CAT_L7VSADM_COMMON, 17, "l7vsadm::parse_opt_replication_switch_func", __FILE__, __LINE__);
1529
1530         if (request.replication_command != l7vsadm_request::REP_NONE) {
1531                 // double command target.
1532                 std::string buf("replication option is double specified.(--switch)");
1533                 l7vsadm_err.setter(true, buf);
1534                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 61, buf, __FILE__, __LINE__);
1535                 return false;
1536         }
1537         if (++pos >= argc) {
1538                 // replication switch value is not specified
1539                 std::string buf("replication switch option is not specified.(--switch)");
1540                 l7vsadm_err.setter(true, buf);
1541                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 62, buf, __FILE__, __LINE__);
1542                 return false;
1543         }
1544         parse_opt_map_type::iterator itr = replication_switch_option_dic.find(argv[pos]);
1545         if (itr != replication_switch_option_dic.end()) { // option string function find.
1546                 if (! itr->second(pos, argc, argv)) return false; // option string function error.
1547         } else { //option string function not found.
1548                 // print option not found message.
1549                 std::stringstream buf;
1550                 buf << "replication switch option not found(--switch): " << argv[pos];
1551                 l7vsadm_err.setter(true, buf.str());
1552                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 63, buf.str(), __FILE__, __LINE__);
1553                 return false;
1554         }
1555         return true;
1556 }
1557 //! replication start function
1558 //! @param[in] argument position
1559 //! @param[in] argument count
1560 //! @param[in] argument value
1561 bool l7vs::l7vsadm::parse_opt_replication_start_func(int &pos, int argc, char *argv[])
1562 {
1563         Logger logger(LOG_CAT_L7VSADM_COMMON, 18, "l7vsadm::parse_opt_replication_start_func", __FILE__, __LINE__);
1564
1565         request.replication_command = l7vsadm_request::REP_START;
1566         return true;
1567 }
1568 //! replication stop function
1569 //! @param[in] argument position
1570 //! @param[in] argument count
1571 //! @param[in] argument value
1572 bool l7vs::l7vsadm::parse_opt_replication_stop_func(int &pos, int argc, char *argv[])
1573 {
1574         Logger logger(LOG_CAT_L7VSADM_COMMON, 19, "l7vsadm::parse_opt_replication_stop_func", __FILE__, __LINE__);
1575
1576         request.replication_command = l7vsadm_request::REP_STOP;
1577         return true;
1578 }
1579 //! replication force function
1580 //! @param[in] argument position
1581 //! @param[in] argument count
1582 //! @param[in] argument value
1583 bool l7vs::l7vsadm::parse_opt_replication_force_func(int &pos, int argc, char *argv[])
1584 {
1585         Logger logger(LOG_CAT_L7VSADM_COMMON, 20, "l7vsadm::parse_opt_replication_force_func", __FILE__, __LINE__);
1586
1587         if (request.replication_command != l7vsadm_request::REP_NONE) {
1588                 // double command target.
1589                 std::string buf("replication option is double specified.(--force)");
1590                 l7vsadm_err.setter(true, buf);
1591                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 64, buf, __FILE__, __LINE__);
1592                 return false;
1593         }
1594         request.replication_command = l7vsadm_request::REP_FORCE;
1595         return true;
1596 }
1597 //! replication dump function
1598 //! @param[in] argument position
1599 //! @param[in] argument count
1600 //! @param[in] argument value
1601 bool l7vs::l7vsadm::parse_opt_replication_dump_func(int &pos, int argc, char *argv[])
1602 {
1603         Logger logger(LOG_CAT_L7VSADM_COMMON, 21, "l7vsadm::parse_opt_replication_dump_func", __FILE__, __LINE__);
1604
1605         if (request.replication_command != l7vsadm_request::REP_NONE) {
1606                 // double command target.
1607                 std::string buf("replication option is double specified.(--dump)");
1608                 l7vsadm_err.setter(true, buf);
1609                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 65, buf, __FILE__, __LINE__);
1610                 return false;
1611         }
1612         request.replication_command = l7vsadm_request::REP_DUMP;
1613         return true;
1614 }
1615
1616 //! log command parsing.
1617 //! @param[in] request command
1618 //! @param[in] argument count
1619 //! @param[in] argument value
1620 bool l7vs::l7vsadm::parse_log_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
1621 {
1622         Logger logger(LOG_CAT_L7VSADM_COMMON, 22, "l7vsadm::parse_log_func", __FILE__, __LINE__);
1623
1624         if (argc != 6) {
1625                 //argument num err
1626                 std::stringstream buf;
1627                 buf << "Argument argc is illegal for ";
1628                 buf << argv[1];
1629                 buf << " command.";
1630
1631                 l7vsadm_err.setter(true, buf.str());
1632                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 124, buf.str(), __FILE__, __LINE__);
1633                 return false;
1634         }
1635
1636         request.command = cmd;
1637
1638         for (int pos = 2; pos < argc; ++pos) {
1639                 parse_opt_map_type::iterator itr = log_option_dic.find(argv[pos]);
1640                 if (itr != log_option_dic.end()) { // option string function find.
1641                         if (! itr->second(pos, argc, argv)) return false; // option string function error.
1642                 } else { //option string function not found.
1643                         // print option not found message.
1644                         std::stringstream buf;
1645                         buf << "log option not found(--log): " << argv[pos];
1646                         l7vsadm_err.setter(true, buf.str());
1647                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 66, buf.str(), __FILE__, __LINE__);
1648                         return false;
1649                 }
1650         }
1651         if (LOG_CAT_NONE == request.log_category) {
1652                 // not specified logcategory
1653                 std::string buf("log category is not specified(--category).");
1654                 l7vsadm_err.setter(true, buf);
1655                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 67, buf, __FILE__, __LINE__);
1656                 return false;
1657         }
1658         if (LOG_LV_NONE == request.log_level) {
1659                 // not specified loglevel
1660                 std::string buf("log level is not specified.(--level)");
1661                 l7vsadm_err.setter(true, buf);
1662                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 68, buf, __FILE__, __LINE__);
1663                 return false;
1664         }
1665
1666         return true;
1667 }
1668 //
1669 // log option function
1670 //
1671 //! log category set function
1672 //! @param[in] argument position
1673 //! @param[in] argument count
1674 //! @param[in] argument value
1675 bool l7vs::l7vsadm::parse_opt_log_category_func(int &pos, int argc, char *argv[])
1676 {
1677         Logger logger(LOG_CAT_L7VSADM_COMMON, 23, "l7vsadm::parse_opt_log_category_func", __FILE__, __LINE__);
1678
1679         if (request.log_category != LOG_CAT_NONE) {
1680                 // double target commands.
1681                 std::stringstream buf;
1682                 buf << "Option ";
1683                 buf << argv[pos];
1684                 buf << " conflict.";
1685
1686                 l7vsadm_err.setter(true, buf.str());
1687                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 69, buf.str(), __FILE__, __LINE__);
1688                 return false;
1689         }
1690         if (++pos >= argc) {
1691                 // log category is not specified.
1692                 std::string buf("log category is not specified.(--category)");
1693                 l7vsadm_err.setter(true, buf);
1694                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 70, buf, __FILE__, __LINE__);
1695                 return false;
1696         }
1697         string_logcategory_map_type::iterator itr = string_logcategory_dic.find(argv[pos]);
1698         if (itr != string_logcategory_dic.end()) {
1699                 request.log_category = itr->second;
1700                 return true;
1701         }
1702         std::stringstream buf;
1703         buf << "log category not found(--category): " << argv[pos];
1704         l7vsadm_err.setter(true, buf.str());
1705         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 71, buf.str(), __FILE__, __LINE__);
1706         return false;
1707 }
1708 //! log level set function
1709 //! @param[in] argument position
1710 //! @param[in] argument count
1711 //! @param[in] argument value
1712 bool l7vs::l7vsadm::parse_opt_log_level_func(int &pos, int argc, char *argv[])
1713 {
1714         Logger logger(LOG_CAT_L7VSADM_COMMON, 24, "l7vsadm::parse_opt_log_level_func", __FILE__, __LINE__);
1715
1716         if (request.log_level != LOG_LV_NONE) {
1717                 // double target commands.
1718                 std::stringstream buf;
1719                 buf << "Option ";
1720                 buf << argv[pos];
1721                 buf << " conflict.";
1722
1723                 l7vsadm_err.setter(true, buf.str());
1724                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 72, buf.str(), __FILE__, __LINE__);
1725                 return false;
1726         }
1727         if (++pos >= argc) {
1728                 // log level is not specified.
1729                 std::string buf("log level is not specified.(--level)");
1730                 l7vsadm_err.setter(true, buf);
1731                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 73, buf, __FILE__, __LINE__);
1732                 return false;
1733         }
1734         string_loglevel_map_type::iterator itr = string_loglevel_dic.find(argv[pos]);
1735         if (itr != string_loglevel_dic.end()) {
1736                 request.log_level = itr->second;
1737                 return true;
1738         }
1739         std::stringstream buf;
1740         buf << "log level not found(--level): " << argv[pos];
1741         l7vsadm_err.setter(true, buf.str());
1742         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 74, buf.str(), __FILE__, __LINE__);
1743         return false;
1744 }
1745
1746 //! snmp command parsing
1747 //! @param[in] request command
1748 //! @param[in] argument count
1749 //! @param[in] argument value
1750 bool l7vs::l7vsadm::parse_snmp_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
1751 {
1752         Logger logger(LOG_CAT_L7VSADM_COMMON, 25, "l7vsadm::parse_snmp_func", __FILE__, __LINE__);
1753
1754         //Argument argc is illegal
1755         if (argc < 3) {
1756                 //argument num err
1757                 std::stringstream buf;
1758                 buf << "Argument argc is illegal for ";
1759                 buf << argv[1];
1760                 buf << " command.";
1761
1762                 l7vsadm_err.setter(true, buf.str());
1763                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 127, buf.str(), __FILE__, __LINE__);
1764                 return false;
1765         }
1766
1767         request.command = cmd;
1768
1769         for (int pos = 2; pos < argc; ++pos) {
1770                 parse_opt_map_type::iterator itr = snmp_option_dic.find(argv[pos]);
1771                 if (itr != snmp_option_dic.end()) { // option string function find.
1772                         if (! itr->second(pos, argc, argv)) return false; // option string function error.
1773                 } else { //option string function not found.
1774                         // print option not found message.
1775                         std::string buf = "Invalid option for -S command.";
1776                         l7vsadm_err.setter(true, buf);
1777                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 128, buf, __FILE__, __LINE__);
1778                         return false;
1779                 }
1780         }
1781
1782         return true;
1783
1784 }
1785 //! snmp refresh set function
1786 //! @param[in]    argument position
1787 //! @param[in]    argument count
1788 //! @param[in]    argument value
1789 bool    l7vs::l7vsadm::parse_opt_snmp_refresh_func(int &pos, int argc, char *argv[])
1790 {
1791         Logger    logger(LOG_CAT_L7VSADM_COMMON, 42, "l7vsadm::parse_opt_snmp_refresh_func", __FILE__, __LINE__);
1792         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_REFRESH_ALL_OPTION_FLAG
1793             || request.snmpinfo.option_set_flag & snmp_info::SNMP_REFRESH_OPTION_FLAG) {
1794                 // double target commands.
1795                 std::stringstream buf;
1796                 buf << "Option ";
1797                 buf << argv[pos];
1798                 buf << " is conflict.";
1799
1800                 l7vsadm_err.setter(true, buf.str());
1801                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 129, buf.str(), __FILE__, __LINE__);
1802                 return false;
1803         }
1804
1805         if (pos != 2) {
1806                 // don't target logcategory
1807                 std::string    buf("Invalid option for -S command.");
1808                 l7vsadm_err.setter(true, buf);
1809                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 130, buf, __FILE__, __LINE__);
1810                 return false;
1811         }
1812
1813         if (argc == 3) {
1814                 request.snmpinfo.option_set_flag |= snmp_info::SNMP_REFRESH_ALL_OPTION_FLAG;
1815                 return true;
1816         } else if (argc == 7) {
1817                 for (pos = 3; pos < argc; ++pos) {
1818                         parse_opt_map_type::iterator itr = snmp_vs_option_dic.find(argv[pos]);
1819                         if (itr != snmp_vs_option_dic.end()) {
1820                                 if (!itr->second(pos, argc, argv)) {
1821                                         return false;
1822                                 }
1823                         } else {
1824                                 std::string    buf("Invalid option value for -r option.");
1825                                 l7vsadm_err.setter(true, buf);
1826                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 78, buf, __FILE__, __LINE__);
1827                                 return false;
1828                         }
1829                 }
1830                 request.snmpinfo.option_set_flag |= snmp_info::SNMP_REFRESH_OPTION_FLAG;
1831
1832         } else {
1833                 std::string    buf("Argument argc is illegal for -S command.");
1834                 l7vsadm_err.setter(true, buf);
1835                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 79, buf, __FILE__, __LINE__);
1836                 return false;
1837         }
1838
1839         return true;
1840 }
1841
1842 //! snmp virtualservice set function
1843 //! @param[in] argument position
1844 //! @param[in] argument count
1845 //! @param[in] argument value
1846 bool    l7vs::l7vsadm::parse_opt_snmp_vs_target_func(int &pos, int argc, char *argv[])
1847 {
1848         Logger    logger(LOG_CAT_L7VSADM_COMMON, 43, "l7vsadm::parse_opt_vs_target_func", __FILE__, __LINE__);
1849         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_TCP_SERVICE_OPTION_FLAG) {
1850                 std::stringstream buf;
1851                 buf << "Option ";
1852                 buf << argv[pos];
1853                 buf << " is conflict.";
1854
1855                 l7vsadm_err.setter(true, buf.str());
1856                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 131, buf.str(), __FILE__, __LINE__);
1857                 return false;
1858         }
1859
1860         if (++pos >= argc) {
1861                 //don't target recvaddress:port
1862                 std::string    buf("target endpoint is not specified.");
1863                 l7vsadm_err.setter(true, buf);
1864                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 132, buf, __FILE__, __LINE__);
1865                 return false;
1866         }
1867
1868         // get host endpoint from string
1869         std::string
1870         src_str = argv[pos];
1871         error_code    err;
1872         boost::asio::ip::tcp::endpoint tmp_endpoint;
1873         tmp_endpoint = string_to_endpoint<boost::asio::ip::tcp>(src_str, err);
1874         if (err) {
1875                 std::stringstream buf;
1876                 buf << "target endpoint parse error:" << err.get_message() << src_str;
1877                 l7vsadm_err.setter(true, buf.str());
1878                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 133, buf.str(), __FILE__, __LINE__);
1879                 return false;
1880         }
1881
1882         request.snmpinfo.vs_endpoint = tmp_endpoint;
1883         request.snmpinfo.option_set_flag |= snmp_info::SNMP_TCP_SERVICE_OPTION_FLAG;
1884
1885
1886         return true;
1887 }
1888 //! snmp module set function
1889 //! @param[in]    argument position
1890 //! @param[in]    argument count
1891 //! @param[in]    argument value
1892 bool    l7vs::l7vsadm::parse_opt_snmp_vs_module_func(int &pos, int argc, char *argv[])
1893 {
1894         Logger    logger(LOG_CAT_L7VSADM_COMMON, 44, "l7vsadm::parse_opt_snmp_vs_module_func", __FILE__, __LINE__);
1895
1896         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_PROTOCOL_MODULE_OPTION_FLAG) {
1897                 std::stringstream buf;
1898                 buf << "Option ";
1899                 buf << argv[pos];
1900                 buf << " is conflict.";
1901
1902                 l7vsadm_err.setter(true, buf.str());
1903                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 134, buf.str(), __FILE__, __LINE__);
1904                 return false;
1905         }
1906
1907         if (++pos >= argc) {
1908                 //don't target protomod name.
1909                 std::string    buf("protomod name is not specified.");
1910                 l7vsadm_err.setter(true, buf);
1911                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 135, buf, __FILE__, __LINE__);
1912                 return false;
1913         }
1914
1915         std::string    module_name = argv[pos];
1916         if (L7VS_MODNAME_LEN < module_name.length()) {
1917                 std::string    buf("protomod name is too long.");
1918                 l7vsadm_err.setter(true, buf);
1919                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 136, buf, __FILE__, __LINE__);
1920                 return false;
1921         }
1922
1923         protocol_module_control    &ctrl = protocol_module_control::getInstance();
1924         ctrl.initialize(L7VS_MODULE_PATH);
1925         protocol_module_base *module;
1926
1927         module = ctrl.load_module(module_name);
1928         if (!module) {
1929                 //don't find protocol module.
1930                 std::stringstream buf;
1931                 buf << "protocol module not found:" << module_name;
1932                 l7vsadm_err.setter(true, buf.str());
1933                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 137, buf.str(), __FILE__, __LINE__);
1934                 return false;
1935         }
1936
1937
1938         ctrl.unload_module(module);
1939
1940         request.snmpinfo.option_set_flag |= snmp_info::SNMP_PROTOCOL_MODULE_OPTION_FLAG ;
1941         request.snmpinfo.protocol = module_name;
1942
1943
1944         return true;
1945 }
1946 //! snmp flag set function
1947 //! @param[in] argument position
1948 //! @param[in] argument count
1949 //! @param[in] argument value
1950 bool    l7vs::l7vsadm::parse_opt_snmp_flag_func(int &pos, int argc, char *argv[])
1951 {
1952         int tmp = 0;
1953         Logger    logger(LOG_CAT_L7VSADM_COMMON, 45, "l7vsadm::parse_opt_snmp_flag_func", __FILE__, __LINE__);
1954         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_ENABLE_OPTION_FLAG) {
1955                 std::stringstream buf;
1956                 buf << "Option ";
1957                 buf << argv[pos];
1958                 buf << " is conflict.";
1959
1960                 l7vsadm_err.setter(true, buf.str());
1961                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 138, buf.str(), __FILE__, __LINE__);
1962                 return false;
1963         }
1964         if (++pos < argc) {
1965                 try {
1966                         tmp = boost::lexical_cast< int >(argv[pos]);
1967                 } catch (const boost::bad_lexical_cast &ex) {
1968                         std::string    buf("Invalid option value for -f option.");
1969                         l7vsadm_err.setter(true, buf);
1970                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 139, buf, __FILE__, __LINE__);
1971                         return false;
1972                 }
1973
1974                 if (tmp == 0 || tmp == 1) {
1975
1976                         request.snmpinfo.enabled = tmp;
1977                         request.snmpinfo.option_set_flag |= snmp_info::SNMP_ENABLE_OPTION_FLAG;
1978
1979                         return true;
1980                 } else {
1981                         std::string    buf("Invalid option value for -f option.");
1982                         l7vsadm_err.setter(true, buf);
1983                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 140, buf, __FILE__, __LINE__);
1984                         return false;
1985                 }
1986         } else {
1987                 std::string    buf("Need option value for -f option.");
1988                 l7vsadm_err.setter(true, buf);
1989                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 141, buf, __FILE__, __LINE__);
1990                 return false;
1991         }
1992 }
1993 //! snmp interval set function
1994 //! @param[in]    argument position
1995 //! @param[in]    argument count
1996 //! @param[in]    argument value
1997 bool    l7vs::l7vsadm::parse_opt_snmp_interval_func(int &pos, int argc, char *argv[])
1998 {
1999         int tmp = 0;
2000         Logger    logger(LOG_CAT_L7VSADM_COMMON, 46, "l7vs::l7vsadm::parse_opt_snmp_interval_func", __FILE__, __LINE__);
2001
2002         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_INTERVAL_OPTION_FLAG) {
2003                 std::stringstream buf;
2004                 buf << "Option ";
2005                 buf << argv[pos];
2006                 buf << " is conflict.";
2007
2008                 l7vsadm_err.setter(true, buf.str());
2009                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 142, buf.str(), __FILE__, __LINE__);
2010                 return false;
2011         }
2012
2013         if (++pos < argc) {
2014                 try {
2015                         tmp = boost::lexical_cast< int >(argv[pos]);
2016                 } catch (const boost::bad_lexical_cast &) {
2017                         std::string    buf("Invalid option value for -i option.");
2018                         l7vsadm_err.setter(true, buf);
2019                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 143, buf, __FILE__, __LINE__);
2020                         return false;
2021                 }
2022
2023                 if (tmp >= 0) {
2024                         request.snmpinfo.interval = tmp;
2025                         request.snmpinfo.option_set_flag |= snmp_info::SNMP_INTERVAL_OPTION_FLAG;
2026
2027                         return true;
2028                 } else {
2029                         std::string    buf("Invalid option value for -i option.");
2030                         l7vsadm_err.setter(true, buf);
2031                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 144, buf, __FILE__, __LINE__);
2032                         return false;
2033                 }
2034         } else    {
2035                 std::string    buf("Need option value for -i option.");
2036                 l7vsadm_err.setter(true, buf);
2037                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 145, buf, __FILE__, __LINE__);
2038                 return false;
2039         }
2040 }
2041
2042 //! snmp logtrap set function
2043 //! @param[in]    argument position
2044 //! @param[in]    argument count
2045 //! @param[in]    argument value
2046 bool    l7vs::l7vsadm::parse_opt_snmp_log_trap_func(int &pos, int argc, char *argv[])
2047 {
2048         int tmp = 0;
2049         Logger    logger(LOG_CAT_L7VSADM_COMMON, 47, "l7vs::l7vsadm::parse_opt_snmp_log_trap_func", __FILE__, __LINE__);
2050
2051         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_LOGTRAP_OPTION_FLAG) {
2052                 std::stringstream buf;
2053                 buf << "Option ";
2054                 buf << argv[pos];
2055                 buf << " is conflict.";
2056
2057                 l7vsadm_err.setter(true, buf.str());
2058                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 146, buf.str(), __FILE__, __LINE__);
2059                 return false;
2060         }
2061         if (++pos < argc) {
2062                 try {
2063                         tmp = boost::lexical_cast< int >(argv[pos]);
2064                 } catch (const boost::bad_lexical_cast &) {
2065                         std::string    buf("Invalid option value for -t option.");
2066                         l7vsadm_err.setter(true, buf);
2067                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 147, buf, __FILE__, __LINE__);
2068                         return false;
2069                 }
2070                 if (tmp == 0 || tmp == 1) {
2071
2072                         request.snmpinfo.logtrap_enabled = tmp;
2073                         request.snmpinfo.option_set_flag |= snmp_info::SNMP_LOGTRAP_OPTION_FLAG;
2074
2075
2076                         return true;
2077                 } else {
2078                         std::string    buf("Invalid option value for -t option.");
2079                         l7vsadm_err.setter(true, buf);
2080                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 148, buf, __FILE__, __LINE__);
2081                         return false;
2082                 }
2083         } else    {
2084                 std::string    buf("Need option value for -t option.");
2085                 l7vsadm_err.setter(true, buf);
2086                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 149, buf, __FILE__, __LINE__);
2087                 return false;
2088         }
2089
2090 }
2091
2092 //! snmp logtrap_level set function
2093 //! @param[in]    argument position
2094 //! @param[in]    argument count
2095 //! @param[in]    argument value
2096 bool    l7vs::l7vsadm::parse_opt_snmp_log_trap_level_func(int &pos, int argc, char *argv[])
2097 {
2098         Logger    logger(LOG_CAT_L7VSADM_COMMON, 48, "l7vs::l7vsadm::parse_opt_snmp_log_trap_level_func", __FILE__, __LINE__);
2099
2100         if (request.snmpinfo.option_set_flag & snmp_info::SNMP_LOGTRAP_LEVEL_OPTION_FLAG) {
2101                 std::stringstream buf;
2102                 buf << "Option ";
2103                 buf << argv[pos];
2104                 buf << " is conflict.";
2105
2106                 l7vsadm_err.setter(true, buf.str());
2107                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 150, buf.str(), __FILE__, __LINE__);
2108                 return false;
2109         }
2110
2111         if (++pos < argc) {
2112                 string_loglevel_map_type::iterator itr = string_loglevel_dic.find(argv[pos]);
2113                 if (itr != string_loglevel_dic.end()) {
2114                         request.snmpinfo.logtrap_level = itr->second;
2115                         request.snmpinfo.option_set_flag |= snmp_info::SNMP_LOGTRAP_LEVEL_OPTION_FLAG;
2116
2117                         return true;
2118                 } else {
2119                         std::stringstream    buf;
2120                         buf << "No such Log-Level " << argv[pos] << ".";
2121                         l7vsadm_err.setter(true, buf.str());
2122                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 151, buf.str(), __FILE__, __LINE__);
2123                         return false;
2124                 }
2125         } else {
2126                 std::string    buf("Need option value for -l option.");
2127                 l7vsadm_err.setter(true, buf);
2128                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 152, buf, __FILE__, __LINE__);
2129                 return false;
2130
2131         }
2132
2133 }
2134
2135 //! parameter command parsing
2136 //! @param[in] request command
2137 //! @param[in] argument count
2138 //! @param[in] argument value
2139 bool l7vs::l7vsadm::parse_parameter_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
2140 {
2141         Logger logger(LOG_CAT_L7VSADM_COMMON, 28, "l7vsadm::parse_parameter_func", __FILE__, __LINE__);
2142
2143         if (argc != 4) {
2144                 //argument num err
2145                 std::stringstream buf;
2146                 buf << "Argument argc is illegal for ";
2147                 buf << argv[1];
2148                 buf << " command.";
2149
2150                 l7vsadm_err.setter(true, buf.str());
2151                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 126, buf.str(), __FILE__, __LINE__);
2152                 return false;
2153         }
2154
2155         request.command = cmd;
2156
2157         for (int pos = 2; pos < argc; ++pos) {
2158                 parse_opt_map_type::iterator itr = parameter_option_dic.find(argv[pos]);
2159                 if (itr != parameter_option_dic.end()) { // option string function find.
2160                         if (! itr->second(pos, argc, argv)) return false; // option string function error.
2161                 } else { //option string function not found.
2162                         // print option not found message.
2163                         std::stringstream buf;
2164                         buf << "parameter option not found(--parameter): " << argv[pos];
2165                         l7vsadm_err.setter(true, buf.str());
2166                         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 84, buf.str(), __FILE__, __LINE__);
2167                         return false;
2168                 }
2169         }
2170
2171         if (PARAM_COMP_NOCAT == request.reload_param) {
2172                 // not specified reload_param
2173                 std::string buf("reload component is not specified.(--reload)");
2174                 l7vsadm_err.setter(true, buf);
2175                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 85, buf, __FILE__, __LINE__);
2176                 return false;
2177         }
2178
2179         return true;
2180 }
2181 //
2182 // parameter command
2183 //
2184 //! parameter reload component parsing
2185 //! @param[in] argument position
2186 //! @param[in] argument count
2187 //! @param[in] argument value
2188 bool l7vs::l7vsadm::parse_opt_parameter_reload_func(int &pos, int argc, char *argv[])
2189 {
2190         Logger logger(LOG_CAT_L7VSADM_COMMON, 29, "l7vsadm::parse_opt_parameter_reload_func", __FILE__, __LINE__);
2191
2192         if (++pos >= argc) {
2193                 // reload component is not specified
2194                 std::string buf("reload component is not specified.(--reload)");
2195                 l7vsadm_err.setter(true, buf);
2196                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 86, buf, __FILE__, __LINE__);
2197                 return false;
2198         }
2199         string_parameter_map_type::iterator itr = string_parameter_dic.find(argv[pos]);
2200         if (itr != string_parameter_dic.end()) {
2201                 request.reload_param = itr->second;
2202                 return true;
2203         }
2204         std::stringstream buf;
2205         buf << "reload component not found(--reload): " << argv[pos];
2206         l7vsadm_err.setter(true, buf.str());
2207         Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 87, buf.str(), __FILE__, __LINE__);
2208         return false;
2209 }
2210
2211 //! help command parsing
2212 //! @param[in] request command
2213 //! @param[in] argument count
2214 //! @param[in] argument value
2215 bool l7vs::l7vsadm::parse_help_func(l7vs::l7vsadm_request::COMMAND_CODE_TAG cmd, int argc, char *argv[])
2216 {
2217         Logger logger(LOG_CAT_L7VSADM_COMMON, 30, "l7vsadm::parse_help_func", __FILE__, __LINE__);
2218
2219         request.command = cmd;
2220
2221         std::cout << usage();
2222
2223         std::cout <<
2224                   "Commands:\n"
2225                   "  --add-service      -A        add virtual service with options\n"
2226                   "  --edit-service     -E        edit virtual service with options\n"
2227                   "  --delete-service   -D        delete virtual service with options\n"
2228                   "  --flush            -C        flush virtual service\n"
2229                   "  --add-server       -a        add real server with options\n"
2230                   "  --edit-server      -e        edit real server with options\n"
2231                   "  --delete-server    -d        delete real server with options\n"
2232                   "  --replication      -R        control replication-function\n"
2233                   "  --log              -L        control logger-function\n"
2234                   "  --snmp             -S        control SNMP Agent-function\n"
2235                   "  --parameter        -P        control parameter-function\n"
2236                   "  --list             -l        list the table\n"
2237                   "  --verbose          -V        list the table in verbose format\n"
2238                   "  --key              -K        list the table in key setting format\n"
2239                   "  --help             -h        show usage\n"
2240                   << std::endl;
2241
2242         std::cout <<
2243                   "Options:\n"
2244                   "  --tcp-service      -t service-address     service-address is host:port\n"
2245                   "  --proto-module     -m proto-module        protocol module name and module argument\n"
2246                   "                        [module-args]\n"
2247                   "  --scheduler        -s scheduler           one of rr,lc,wrr\n"
2248                   "  --upper            -u connection-count    maximum number of connections\n"
2249                   "  --bypass           -b sorry-server        sorry server address is host:port\n"
2250                   "  --tproxy                                  set sorry server connection to IP transparent mode.\n"
2251                   "  --masq                                    set sorry server connection to IP masquerade mode.\n"
2252
2253                   "  --flag             -f sorry-flag          sorry status set to virtual service\n"
2254                   "  --qos-up           -Q QoSval-up           QoS Threshold(bps) set to real server direction\n"
2255                   "  --qos-down         -q QoSval-down         QoS Threshold(bps) set to client direction\n"
2256                   "  --ssl              -z ssl-config-file     SSL configuration file(Use SSL)\n"
2257                   "  --sockopt          -O socket-option       deferaccept,nodelay,cork,quickackon or quickackoff set to socket option\n"
2258                   "  --access-log       -L access-log-flag     access log flag 0(none) or 1(output)\n"
2259                   "  --access-log-name  -a access-log-file     access log file\n"
2260                   "                        [logrotate-args]\n"
2261                   "  --real-server      -r server-address      server-address is host:port\n"
2262                   "  --weight           -w weight              scheduling weight set to real server\n"
2263                   "  --tproxy                                  set real server connection to IP transparent mode.\n"
2264                   "  --masq                                    set real server connection to IP masquerade mode.\n"
2265                   "  --switch           -s replication-switch  start or stop replication\n"
2266                   "  --force            -f                     force replication start\n"
2267                   "  --dump             -d                     dump replication memory\n"
2268                   "  --category         -c log-category        set log category for l7vsd or SNMP Agent\n"
2269                   "  --level            -l log-level           set log level for l7vsd or SNMP Agent\n"
2270                   "  --reload           -r reload-parameter    reload specified config parameter\n"
2271                   "  --numeric          -n                     list the table in numeric\n"
2272                   "  --flag             -f snmp-flag           start or stop snmp function 0(off) 1(on)\n"
2273                   "  --interval         -i update-interval     set collect snmp cache collect interval(s)\n"
2274                   "  --logtrap          -t log-trap-flag       start or stop log trap function 0(off) 1(on)\n"
2275                   "  --logtraplevel     -l log-trap-level      set log trap level for snmp\n"
2276                   "  --refresh          -r                     clear statistic info for snmp\n"
2277                   << std::endl;
2278
2279         return true;
2280 }
2281
2282 //! usage function.
2283 std::string l7vs::l7vsadm::usage()
2284 {
2285         Logger logger(LOG_CAT_L7VSADM_COMMON, 31, "l7vsadm::usage", __FILE__, __LINE__);
2286
2287         std::stringstream stream;
2288         stream <<
2289                "Usage: \n"
2290                "  l7vsadm -A -t service-address -m proto-module [module-args]\n"
2291                "          [-s scheduler] [-u connection-count] [-b sorry-server] [--masq|tproxy]\n"
2292                "          [-f sorry-flag] [-Q QoSval-up] [-q QoSval-down] [-z ssl-config-file]\n"
2293                "          [-O socket-option] [-L access-log-flag] [-a access-log-file [logrotate-args]]\n"
2294                "  l7vsadm -E -t service-address -m proto-module [module-args]\n"
2295                "          [-s scheduler] [-u connection-count] [-b sorry-server] [--masq|tproxy]\n"
2296                "          [-f sorry-flag] [-Q QoSval-up] [-q QoSval-down] [-L access-log-flag]\n"
2297                "  l7vsadm -D -t service-address -m proto-module [module-args]\n"
2298                "  l7vsadm -C\n"
2299                "  l7vsadm -a|e -t service-address -m proto-module [module-args]\n"
2300                "          -r server-address [-w weight] [--masq|tproxy]\n"
2301                "  l7vsadm -d -t service-address -m proto-module [module-args]\n"
2302                "          -r server-address\n"
2303                "  l7vsadm -R -s replication-switch\n"
2304                "  l7vsadm -R -f\n"
2305                "  l7vsadm -R -d\n"
2306                "  l7vsadm -L -c log-category -l log-level\n"
2307                "  l7vsadm -S [-f snmp-flag] [-i update-interval] [-t log-trap-flag] [-l log-trap-level]\n"
2308                "  l7vsadm -S -r [-t service-address -m proto-module]\n"
2309                "  l7vsadm -P -r reload-parameter\n"
2310                "  l7vsadm -l [-n]\n"
2311                "  l7vsadm -V [-n]\n"
2312                "  l7vsadm -K [-n]\n"
2313                "  l7vsadm -h\n"
2314                << std::endl;
2315         return stream.str();
2316 }
2317
2318 //! disp_list function
2319 void l7vs::l7vsadm::disp_list()
2320 {
2321         Logger logger(LOG_CAT_L7VSADM_COMMON, 32, "l7vsadm::disp_list", __FILE__, __LINE__);
2322
2323         std::stringstream buf;
2324         buf << boost::format("Layer-7 Virtual Server version %s\n") % VERSION;
2325         buf << "Prot LocalAddress:Port ProtoMod Scheduler\n";
2326         buf << "  -> RemoteAddress:Port           Forward Weight ActiveConn InactConn\n";
2327         BOOST_FOREACH(virtualservice_element vse, response.virtualservice_status_list) {
2328                 std::string vsepstr;
2329                 if (vse.udpmode) {
2330                         vsepstr = endpoint_to_string<boost::asio::ip::udp>(vse.udp_recv_endpoint, numeric_flag);
2331                 } else {
2332                         vsepstr = endpoint_to_string<boost::asio::ip::tcp>(vse.tcp_accept_endpoint, numeric_flag);
2333                 }
2334                 buf << boost::format("%s %s %s %s\n")
2335                     % (vse.udpmode ? "UDP" : "TCP")
2336                     % vsepstr
2337                     % vse.protocol_module_name
2338                     % vse.schedule_module_name;
2339                 BOOST_FOREACH(realserver_element rse, vse.realserver_vector) {
2340                         std::string rsepstr;
2341                         if (vse.udpmode) {
2342                                 rsepstr = endpoint_to_string<boost::asio::ip::udp>(rse.udp_endpoint, numeric_flag);
2343                         } else {
2344                                 rsepstr = endpoint_to_string<boost::asio::ip::tcp>(rse.tcp_endpoint, numeric_flag);
2345                         }
2346                         buf << boost::format("  -> %-28s %-7s %-6d %-10d %-10d\n")
2347                             % rsepstr
2348                             % rse.get_fwdmode_str()
2349                             % rse.weight
2350                             % rse.get_active()
2351                             % rse.get_inact();
2352                 }
2353         }
2354         std::cout << buf.str();
2355 }
2356
2357 //! disp_list_key function
2358 void l7vs::l7vsadm::disp_list_key()
2359 {
2360         Logger logger(LOG_CAT_L7VSADM_COMMON, 33, "l7vsadm::disp_list_key", __FILE__, __LINE__);
2361
2362         std::stringstream buf;
2363         buf << boost::format("Layer-7 Virtual Server version %s\n") % VERSION;
2364         buf << "Prot LocalAddress:Port ProtoMod Scheduler\n";
2365         buf << "     SSL_config_file\n";
2366         buf << "     Socket option\n";
2367         buf << "     Access_log_flag\n";
2368         buf << "     Access_log_file\n";
2369         buf << "     Access_log_rotate option\n";
2370         buf << "  -> RemoteAddress:Port           Forward Weight ActiveConn InactConn\n";
2371         BOOST_FOREACH(virtualservice_element vse, response.virtualservice_status_list) {
2372                 std::string vsepstr;
2373                 if (vse.udpmode) {
2374                         vsepstr = endpoint_to_string<boost::asio::ip::udp>(vse.udp_recv_endpoint, numeric_flag);
2375                 } else {
2376                         vsepstr = endpoint_to_string<boost::asio::ip::tcp>(vse.tcp_accept_endpoint, numeric_flag);
2377                 }
2378                 buf << boost::format("%s %s %s %s\n")
2379                     % (vse.udpmode ? "UDP" : "TCP")
2380                     % vsepstr
2381                     % vse.protocol_module_name
2382                     % vse.schedule_module_name;
2383                 buf << boost::format("    %s\n")
2384                     % ((0 == vse.ssl_file_name.length()) ? "none" : vse.ssl_file_name);
2385                 buf << boost::format("    %s\n")
2386                     % ((0 == vse.socket_option_string.length()) ? "none" : vse.socket_option_string);
2387                 buf << boost::format("    %d\n") % vse.access_log_flag;
2388                 buf << boost::format("    %s\n")
2389                     % ((0 == vse.access_log_file_name.length()) ? "none" : vse.access_log_file_name);
2390                 buf << boost::format("    %s\n")
2391                     % ((0 == vse.access_log_rotate_key_info.length()) ? "none" :  vse.access_log_rotate_key_info);
2392
2393                 BOOST_FOREACH(realserver_element rse, vse.realserver_vector) {
2394                         std::string    rsepstr;
2395                         if (vse.udpmode)
2396                                 rsepstr = endpoint_to_string<boost::asio::ip::udp>(rse.udp_endpoint, numeric_flag);
2397                         else
2398                                 rsepstr = endpoint_to_string<boost::asio::ip::tcp>(rse.tcp_endpoint, numeric_flag);
2399                         buf << boost::format("  -> %-28s %-7s %-6d %-10d %-10d\n")
2400                             % rsepstr
2401                             % rse.get_fwdmode_str()
2402                             % rse.weight
2403                             % rse.get_active()
2404                             % rse.get_inact();
2405                 }
2406         }
2407         std::cout << buf.str();
2408 }
2409
2410 //! disp_list_verbose function
2411 void l7vs::l7vsadm::disp_list_verbose()
2412 {
2413         Logger logger(LOG_CAT_L7VSADM_COMMON, 34, "l7vsadm::disp_list_verbose", __FILE__, __LINE__);
2414
2415         unsigned long long output_qos_upstream_value;
2416         unsigned long long output_qos_downstream_value;
2417         const int MAX_TIME_FORMAT_LEN = 20;
2418         char snmp_start_date[MAX_TIME_FORMAT_LEN] = {0};
2419         char snmp_last_request_date[MAX_TIME_FORMAT_LEN] = {0};
2420         char snmp_last_trap_date[MAX_TIME_FORMAT_LEN] = {0};
2421
2422         std::stringstream buf;
2423         buf << boost::format("Layer-7 Virtual Server version %s\n") % VERSION;
2424
2425         //disp loglevel
2426         buf << "L7vsd Log Level:\n";
2427         buf << "Category                       Level\n";
2428         typedef std::pair<LOG_CATEGORY_TAG, LOG_LEVEL_TAG> logstatus_type;
2429         BOOST_FOREACH(logstatus_type logstatus, response.log_status_list) {
2430                 buf << boost::format("%-30s %s\n")
2431                     % logcategory_string_dic[logstatus.first]
2432                     % loglevel_string_dic[logstatus.second];
2433         }
2434         buf << "\n";
2435
2436         //disp replication
2437         buf << "Replication Mode:\n";
2438         buf << boost::format("%s\n") % replication_mode_string_dic[response.replication_mode_status];
2439         buf << "\n";
2440
2441         //disp snmp agent status
2442         buf << "SNMPAgent:\n";
2443         if (!response.snmpinfo.enabled) {
2444                 boost::format fmtter("%-30s inactive\n"
2445                                      "%-30s none\n"
2446                                      "%-30s none\n"
2447                                      "%-30s none\n"
2448                                      "%-30s none\n"
2449                                      "%-30s none\n"
2450                                      "%-30s none\n"
2451                                      "%-30s none\n"
2452                                      "%-30s none\n"
2453                                      "%-30s none\n");
2454
2455                 fmtter % "Agent Status";
2456                 fmtter % "log trap status";
2457                 fmtter % "log trap level";
2458                 fmtter % "cache update interval";
2459                 fmtter % "start date";
2460                 fmtter % "last request date";
2461                 fmtter % "last trap date";
2462                 fmtter % "total GET requests";
2463                 fmtter % "total SET requests";
2464                 fmtter % "total trap counts";
2465
2466                 buf << fmtter.str();
2467         } else {
2468                 strftime(snmp_start_date, sizeof(snmp_start_date), "%Y-%m-%d %H:%M:%S", localtime(&response.snmpinfo.start_date));
2469                 strftime(snmp_last_request_date, sizeof(snmp_start_date), "%Y-%m-%d %H:%M:%S", localtime(&response.snmpinfo.request_last_date));
2470                 strftime(snmp_last_trap_date, sizeof(snmp_start_date), "%Y-%m-%d %H:%M:%S", localtime(&response.snmpinfo.trap_last_date));
2471
2472                 boost::format fmtter("%-30s active\n"
2473                                      "%-30s %s\n"
2474                                      "%-30s %s\n"
2475                                      "%-30s %d\n"
2476                                      "%-30s %s\n"
2477                                      "%-30s %s\n"
2478                                      "%-30s %s\n"
2479                                      "%-30s %u\n"
2480                                      "%-30s %u\n"
2481                                      "%-30s %u\n");
2482
2483                 fmtter % "Agent Status";
2484                 fmtter % "log trap status";
2485                 fmtter % (response.snmpinfo.logtrap_enabled ? "on" : "off");
2486                 fmtter % "log trap level";
2487                 fmtter % (response.snmpinfo.logtrap_enabled ? loglevel_string_dic[response.snmpinfo.logtrap_level] : "none");
2488                 fmtter % "cache update interval" % response.snmpinfo.interval;
2489                 fmtter % "start date" % (response.snmpinfo.start_date == 0 ? "none" : snmp_start_date);
2490                 fmtter % "last request date" % (response.snmpinfo.request_last_date == 0 ? "none" : snmp_last_request_date);
2491                 fmtter % "last trap date" % (response.snmpinfo.trap_last_date == 0 ? "none" : snmp_last_trap_date);
2492                 fmtter % "total GET requests" % response.snmpinfo.snmp_get_requests;
2493                 fmtter % "total SET requests" % response.snmpinfo.snmp_set_requests;
2494                 fmtter % "total trap counts" % response.snmpinfo.snmp_trap_count;
2495                 buf << fmtter.str();
2496         }
2497
2498
2499         buf << "\n";
2500
2501         // disp vs
2502         buf << "Prot LocalAddress:Port ProtoMod Scheduler Protomod_opt_string\n";
2503         buf << "  -> RemoteAddress:Port           Forward Weight ActiveConn InactConn\n";
2504         BOOST_FOREACH(virtualservice_element vse, response.virtualservice_status_list) {
2505                 std::string vsepstr;
2506                 if (vse.udpmode) {
2507                         vsepstr = endpoint_to_string<boost::asio::ip::udp>(vse.udp_recv_endpoint, numeric_flag);
2508                 } else {
2509                         vsepstr = endpoint_to_string<boost::asio::ip::tcp>(vse.tcp_accept_endpoint, numeric_flag);
2510                 }
2511
2512                 if (vse.qos_upstream == ULLONG_MAX) {
2513                         output_qos_upstream_value = 0;
2514                 } else {
2515                         output_qos_upstream_value = vse.qos_upstream * 8;
2516                 }
2517
2518                 if (vse.qos_downstream == ULLONG_MAX) {
2519                         output_qos_downstream_value = 0;
2520                 } else {
2521                         output_qos_downstream_value = vse.qos_downstream * 8;
2522                 }
2523
2524                 buf << boost::format("%s %s %s %s %s\n")
2525                     % (vse.udpmode ? "UDP" : "TCP")
2526                     % vsepstr
2527                     % vse.protocol_module_name
2528                     % vse.schedule_module_name
2529                     % vse.protocol_module_for_indication_options;
2530
2531                 BOOST_FOREACH(realserver_element rse, vse.realserver_vector) {
2532                         std::string rsepstr;
2533                         if (vse.udpmode) {
2534                                 rsepstr = endpoint_to_string<boost::asio::ip::udp>(rse.udp_endpoint, numeric_flag);
2535                         } else {
2536                                 rsepstr = endpoint_to_string<boost::asio::ip::tcp>(rse.tcp_endpoint, numeric_flag);
2537                         }
2538                         buf << boost::format("  -> %-28s %-7s %-6d %-10d %-10d\n")
2539                             % rsepstr
2540                             % rse.get_fwdmode_str()
2541                             % rse.weight
2542                             % rse.get_active()
2543                             % rse.get_inact();
2544                 }
2545
2546                 if (!vse.udpmode) {
2547                         std::string    sorryepstr;
2548                         std::string    sorry_flag_str;
2549                         boost::asio::ip::tcp::endpoint    zeropoint;
2550                         if (zeropoint == vse.sorry_endpoint) {
2551                                 sorryepstr = "none";
2552                         } else {
2553                                 sorryepstr = endpoint_to_string<boost::asio::ip::tcp>(vse.sorry_endpoint,
2554                                                 numeric_flag) + " " + vse.get_fwdmode_str();
2555                         }
2556
2557                         if (vse.sorry_flag) {
2558                                 sorry_flag_str = "on";
2559                         } else {
2560                                 sorry_flag_str = "off";
2561                         }
2562
2563                         buf << boost::format("  Bypass Settings:\n"
2564                                              "    Sorry Server                  %s\n"
2565                                              "    Max Connection                %lld\n"
2566                                              "    Sorry Flag                    %s\n")
2567                             % sorryepstr
2568                             % vse.sorry_maxconnection
2569                             % sorry_flag_str;
2570                 }
2571
2572                 buf << boost::format("  SSL Settings:\n"
2573                                      "    SSL Config File               %s\n")
2574                     % ((0 == vse.ssl_file_name.length()) ? "none" : vse.ssl_file_name);
2575
2576                 buf << boost::format("  Logging Settings:\n"
2577                                      "    Access Log                    %s\n"
2578                                      "    Access Log File               %s\n"
2579                                      "    Access Log Rotate             %s\n")
2580                     % ((0 == vse.access_log_flag) ? "off" : "on")
2581                     % ((0 == vse.access_log_file_name.length()) ? "none" : vse.access_log_file_name)
2582                     % ((0 == vse.access_log_rotate_verbose_info.length()) ? "none" :  vse.access_log_rotate_verbose_info);
2583
2584                 buf << boost::format("  Socket Settings:\n"
2585                                      "    TCP_DEFER_ACCEPT              %s\n"
2586                                      "    TCP_NODELAY                   %s\n"
2587                                      "    TCP_CORK                      %s\n"
2588                                      "    TCP_QUICKACK                  %s\n")
2589                     % ((0 == vse.socket_option_tcp_defer_accept) ? "disable" : "enable")
2590                     % ((0 == vse.socket_option_tcp_nodelay) ? "disable" : "enable")
2591                     % ((0 == vse.socket_option_tcp_cork) ? "disable" : "enable")
2592                     % ((0 == vse.socket_option_tcp_quickack) ? "auto" : ((1 == vse.socket_option_tcp_quickack) ? "enable" : "disable"));
2593
2594
2595                 buf << boost::format("  Throughput:\n"
2596                                      "    Current Upload / Limit        %f Mbps / %f Mbps\n"
2597                                      "    Current Download / Limit      %f Mbps / %f Mbps\n")
2598                     % ((double)vse.throughput_upstream * 8 / (1000 * 1000)) % ((double)output_qos_upstream_value / (1000 * 1000))
2599                     % ((double)vse.throughput_downstream * 8 / (1000 * 1000)) % ((double)output_qos_downstream_value / (1000 * 1000));
2600
2601                 buf << boost::format("  Statistics:\n"
2602                                      "    HTTP Total Requests           %lld\n"
2603                                      "    HTTP GET Requests             %lld\n"
2604                                      "    HTTP POST Requests            %lld\n")
2605                     % vse.http_total_count % vse.http_get_count % vse.http_post_count;
2606
2607
2608         }
2609         std::cout << buf.str();
2610 }
2611 //! l7vsadm constructor.
2612 //! create including all dictionary.
2613 l7vs::l7vsadm::l7vsadm()
2614         :   numeric_flag(false),
2615             command_wait_interval(L7VSADM_DEFAULT_WAIT_INTERVAL),
2616             command_wait_count(L7VSADM_DEFAULT_WAIT_COUNT)
2617 {
2618         Logger logger(LOG_CAT_L7VSADM_COMMON, 35, "l7vsadm::l7vsadm(constructor)", __FILE__, __LINE__);
2619
2620         // create command dictionary.
2621         command_dic["-l"]               = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST, _1, _2);
2622         command_dic["--list"]           = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST, _1, _2);
2623         command_dic["-V"]               = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST_VERBOSE, _1, _2);
2624         command_dic["--verbose"]        = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST_VERBOSE, _1, _2);
2625         command_dic["-K"]               = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST_KEY, _1, _2);
2626         command_dic["--key"]            = boost::bind(&l7vsadm::parse_list_func, this, l7vsadm_request::CMD_LIST_KEY, _1, _2);
2627         command_dic["-A"]               = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_ADD_VS, _1, _2);
2628         command_dic["--add-service"]    = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_ADD_VS, _1, _2);
2629         command_dic["-D"]               = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_DEL_VS, _1, _2);
2630         command_dic["--delete-service"] = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_DEL_VS, _1, _2);
2631         command_dic["-E"]               = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_EDIT_VS, _1, _2);
2632         command_dic["--edit-service"]   = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_EDIT_VS, _1, _2);
2633         command_dic["-C"]               = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_FLUSH_VS, _1, _2);
2634         command_dic["--flush"]          = boost::bind(&l7vsadm::parse_vs_func, this, l7vsadm_request::CMD_FLUSH_VS, _1, _2);
2635         command_dic["-a"]               = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_ADD_RS, _1, _2);
2636         command_dic["--add-server"]     = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_ADD_RS, _1, _2);
2637         command_dic["-d"]               = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_DEL_RS, _1, _2);
2638         command_dic["--delete-server"]  = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_DEL_RS, _1, _2);
2639         command_dic["-e"]               = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_EDIT_RS, _1, _2);
2640         command_dic["--edit-server"]    = boost::bind(&l7vsadm::parse_rs_func, this, l7vsadm_request::CMD_EDIT_RS, _1, _2);
2641         command_dic["-R"]               = boost::bind(&l7vsadm::parse_replication_func, this, l7vsadm_request::CMD_REPLICATION, _1, _2);
2642         command_dic["--replication"]    = boost::bind(&l7vsadm::parse_replication_func, this, l7vsadm_request::CMD_REPLICATION, _1, _2);
2643         command_dic["-L"]               = boost::bind(&l7vsadm::parse_log_func, this, l7vsadm_request::CMD_LOG, _1, _2);
2644         command_dic["--log"]            = boost::bind(&l7vsadm::parse_log_func, this, l7vsadm_request::CMD_LOG, _1, _2);
2645         command_dic["-S"]               = boost::bind(&l7vsadm::parse_snmp_func, this, l7vsadm_request::CMD_SNMP, _1, _2);
2646         command_dic["--snmp"]           = boost::bind(&l7vsadm::parse_snmp_func, this, l7vsadm_request::CMD_SNMP, _1, _2);
2647         command_dic["-P"]               = boost::bind(&l7vsadm::parse_parameter_func, this, l7vsadm_request::CMD_PARAMETER, _1, _2);
2648         command_dic["--parameter"]      = boost::bind(&l7vsadm::parse_parameter_func, this, l7vsadm_request::CMD_PARAMETER, _1, _2);
2649         command_dic["-h"]               = boost::bind(&l7vsadm::parse_help_func, this, l7vsadm_request::CMD_HELP, _1, _2);
2650         command_dic["--help"]           = boost::bind(&l7vsadm::parse_help_func, this, l7vsadm_request::CMD_HELP, _1, _2);
2651
2652         // create list option dictionary.
2653         list_option_dic["-n"]        = boost::bind(&l7vsadm::parse_opt_list_numeric_func, this, _1, _2, _3);
2654         list_option_dic["--numeric"] = boost::bind(&l7vsadm::parse_opt_list_numeric_func, this, _1, _2, _3);
2655
2656         // create virtualservice option dictionary
2657         vs_option_dic["-t"]                = boost::bind(&l7vsadm::parse_opt_vs_target_func, this, _1, _2, _3);
2658         vs_option_dic["--tcp-service"]     = boost::bind(&l7vsadm::parse_opt_vs_target_func, this, _1, _2, _3);
2659         vs_option_dic["-m"]                = boost::bind(&l7vsadm::parse_opt_vs_module_func, this, _1, _2, _3);
2660         vs_option_dic["--proto-module"]    = boost::bind(&l7vsadm::parse_opt_vs_module_func, this, _1, _2, _3);
2661         vs_option_dic["-s"]                = boost::bind(&l7vsadm::parse_opt_vs_scheduler_func, this, _1, _2, _3);
2662         vs_option_dic["--scheduler"]       = boost::bind(&l7vsadm::parse_opt_vs_scheduler_func, this, _1, _2, _3);
2663         vs_option_dic["-u"]                = boost::bind(&l7vsadm::parse_opt_vs_upper_func, this, _1, _2, _3);
2664         vs_option_dic["--upper"]           = boost::bind(&l7vsadm::parse_opt_vs_upper_func, this, _1, _2, _3);
2665         vs_option_dic["-b"]                = boost::bind(&l7vsadm::parse_opt_vs_bypass_func, this, _1, _2, _3);
2666         vs_option_dic["--bypass"]          = boost::bind(&l7vsadm::parse_opt_vs_bypass_func, this, _1, _2, _3);
2667         vs_option_dic["--tproxy"]          = boost::bind(&l7vsadm::parse_opt_vs_fwdmode_func, this, _1, _2, _3);
2668         vs_option_dic["--masq"]            = boost::bind(&l7vsadm::parse_opt_vs_fwdmode_func, this, _1, _2, _3);
2669         vs_option_dic["-f"]                = boost::bind(&l7vsadm::parse_opt_vs_flag_func, this, _1, _2, _3);
2670         vs_option_dic["--flag"]            = boost::bind(&l7vsadm::parse_opt_vs_flag_func, this, _1, _2, _3);
2671         vs_option_dic["-Q"]                = boost::bind(&l7vsadm::parse_opt_vs_qosup_func, this, _1, _2, _3);
2672         vs_option_dic["--qos-up"]          = boost::bind(&l7vsadm::parse_opt_vs_qosup_func, this, _1, _2, _3);
2673         vs_option_dic["-q"]                = boost::bind(&l7vsadm::parse_opt_vs_qosdown_func, this, _1, _2, _3);
2674         vs_option_dic["--qos-down"]        = boost::bind(&l7vsadm::parse_opt_vs_qosdown_func, this, _1, _2, _3);
2675         vs_option_dic["-p"]                = boost::bind(&l7vsadm::parse_opt_vs_udp_func, this, _1, _2, _3);
2676         vs_option_dic["--udp"]             = boost::bind(&l7vsadm::parse_opt_vs_udp_func, this, _1, _2, _3);
2677         vs_option_dic["-z"]                = boost::bind(&l7vsadm::parse_opt_vs_ssl_file_func, this, _1, _2, _3);
2678         vs_option_dic["--ssl"]             = boost::bind(&l7vsadm::parse_opt_vs_ssl_file_func, this, _1, _2, _3);
2679         vs_option_dic["-O"]                = boost::bind(&l7vsadm::parse_opt_vs_socket_func, this, _1, _2, _3);
2680         vs_option_dic["--sockopt"]         = boost::bind(&l7vsadm::parse_opt_vs_socket_func, this, _1, _2, _3);
2681         vs_option_dic["-L"]                = boost::bind(&l7vsadm::parse_opt_vs_access_log_func, this, _1, _2, _3);
2682         vs_option_dic["--access-log"]      = boost::bind(&l7vsadm::parse_opt_vs_access_log_func, this, _1, _2, _3);
2683         vs_option_dic["-a"]                = boost::bind(&l7vsadm::parse_opt_vs_access_log_logrotate_func, this, _1, _2, _3);
2684         vs_option_dic["--access-log-name"] = boost::bind(&l7vsadm::parse_opt_vs_access_log_logrotate_func, this, _1, _2, _3);
2685
2686         // create realserver option dictionary
2687         rs_option_dic["-t"]             = boost::bind(&l7vsadm::parse_opt_vs_target_func, this, _1, _2, _3);
2688         rs_option_dic["--tcp-service"]  = boost::bind(&l7vsadm::parse_opt_vs_target_func, this, _1, _2, _3);
2689         rs_option_dic["-w"]             = boost::bind(&l7vsadm::parse_opt_rs_weight_func, this, _1, _2, _3);
2690         rs_option_dic["--weight"]       = boost::bind(&l7vsadm::parse_opt_rs_weight_func, this, _1, _2, _3);
2691         rs_option_dic["--tproxy"]       = boost::bind(&l7vsadm::parse_opt_rs_fwdmode_func, this, _1, _2, _3);
2692         rs_option_dic["--masq"]         = boost::bind(&l7vsadm::parse_opt_rs_fwdmode_func, this, _1, _2, _3);
2693         rs_option_dic["-m"]             = boost::bind(&l7vsadm::parse_opt_vs_module_func, this, _1, _2, _3);
2694         rs_option_dic["--proto-module"] = boost::bind(&l7vsadm::parse_opt_vs_module_func, this, _1, _2, _3);
2695         rs_option_dic["-p"]             = boost::bind(&l7vsadm::parse_opt_vs_udp_func, this, _1, _2, _3);
2696         rs_option_dic["--udp"]          = boost::bind(&l7vsadm::parse_opt_vs_udp_func, this, _1, _2, _3);
2697         rs_option_dic["-r"]             = boost::bind(&l7vsadm::parse_opt_rs_realserver_func, this, _1, _2, _3);
2698         rs_option_dic["--real-server"]  = boost::bind(&l7vsadm::parse_opt_rs_realserver_func, this, _1, _2, _3);
2699
2700         // create replication option dictionary
2701         replication_option_dic["-s"]           = boost::bind(&l7vsadm::parse_opt_replication_switch_func, this, _1, _2, _3);
2702         replication_option_dic["--switch"]     = boost::bind(&l7vsadm::parse_opt_replication_switch_func, this, _1, _2, _3);
2703         replication_switch_option_dic["start"] = boost::bind(&l7vsadm::parse_opt_replication_start_func, this, _1, _2, _3);
2704         replication_switch_option_dic["stop"]  = boost::bind(&l7vsadm::parse_opt_replication_stop_func, this, _1, _2, _3);
2705         replication_option_dic["-f"]           = boost::bind(&l7vsadm::parse_opt_replication_force_func, this, _1, _2, _3);
2706         replication_option_dic["--force"]      = boost::bind(&l7vsadm::parse_opt_replication_force_func, this, _1, _2, _3);
2707         replication_option_dic["-d"]           = boost::bind(&l7vsadm::parse_opt_replication_dump_func, this, _1, _2, _3);
2708         replication_option_dic["--dump"]       = boost::bind(&l7vsadm::parse_opt_replication_dump_func, this, _1, _2, _3);
2709
2710         // create log option function dictionary create
2711         log_option_dic["-c"]         = boost::bind(&l7vsadm::parse_opt_log_category_func, this, _1, _2, _3);
2712         log_option_dic["--category"] = boost::bind(&l7vsadm::parse_opt_log_category_func, this, _1, _2, _3);
2713         log_option_dic["-l"]         = boost::bind(&l7vsadm::parse_opt_log_level_func, this, _1, _2, _3);
2714         log_option_dic["--level"]    = boost::bind(&l7vsadm::parse_opt_log_level_func, this, _1, _2, _3);
2715
2716         // snmp agent option function dictionary create
2717         snmp_option_dic["-r"]               = boost::bind(&l7vsadm::parse_opt_snmp_refresh_func, this, _1, _2, _3);
2718         snmp_option_dic["--refresh"]        = boost::bind(&l7vsadm::parse_opt_snmp_refresh_func, this, _1, _2, _3);
2719         snmp_option_dic["-f"]            = boost::bind(&l7vsadm::parse_opt_snmp_flag_func, this, _1, _2, _3);
2720         snmp_option_dic["--flag"]        = boost::bind(&l7vsadm::parse_opt_snmp_flag_func, this, _1, _2, _3);
2721         snmp_option_dic["-i"]            = boost::bind(&l7vsadm::parse_opt_snmp_interval_func, this, _1, _2, _3);
2722         snmp_option_dic["--interval"]        = boost::bind(&l7vsadm::parse_opt_snmp_interval_func, this, _1, _2, _3);
2723         snmp_option_dic["-t"]            = boost::bind(&l7vsadm::parse_opt_snmp_log_trap_func, this, _1, _2, _3);
2724         snmp_option_dic["--logtrap"]        = boost::bind(&l7vsadm::parse_opt_snmp_log_trap_func, this, _1, _2, _3);
2725         snmp_option_dic["-l"]            = boost::bind(&l7vsadm::parse_opt_snmp_log_trap_level_func, this, _1, _2, _3);
2726         snmp_option_dic["--logtraplevel"]     = boost::bind(&l7vsadm::parse_opt_snmp_log_trap_level_func, this, _1, _2, _3);
2727         snmp_vs_option_dic["-t"]        = boost::bind(&l7vsadm::parse_opt_snmp_vs_target_func, this, _1, _2, _3);
2728         snmp_vs_option_dic["--tcp-service"]    = boost::bind(&l7vsadm::parse_opt_snmp_vs_target_func, this, _1, _2, _3);
2729         snmp_vs_option_dic["-m"]        = boost::bind(&l7vsadm::parse_opt_snmp_vs_module_func, this, _1, _2, _3);
2730         snmp_vs_option_dic["--proto-module"]    = boost::bind(&l7vsadm::parse_opt_snmp_vs_module_func, this, _1, _2, _3);
2731         // parameter option function dictionary create
2732         parameter_option_dic["-r"]       = boost::bind(&l7vsadm::parse_opt_parameter_reload_func, this, _1, _2, _3);
2733         parameter_option_dic["--reload"] = boost::bind(&l7vsadm::parse_opt_parameter_reload_func, this, _1, _2, _3);
2734
2735         // string logcategory dictionary create
2736         string_logcategory_dic["l7vsd_network"]                      = LOG_CAT_L7VSD_NETWORK;
2737         string_logcategory_dic["nw"]                                 = LOG_CAT_L7VSD_NETWORK;
2738         logcategory_string_dic[LOG_CAT_L7VSD_NETWORK]                = "l7vsd_network";
2739         string_logcategory_dic["l7vsd_network_qos"]                  = LOG_CAT_L7VSD_NETWORK_QOS;
2740         string_logcategory_dic["nw_qos"]                             = LOG_CAT_L7VSD_NETWORK_QOS;
2741         logcategory_string_dic[LOG_CAT_L7VSD_NETWORK_QOS]            = "l7vsd_network_qos";
2742         string_logcategory_dic["l7vsd_network_bandwidth"]            = LOG_CAT_L7VSD_NETWORK_BANDWIDTH;
2743         string_logcategory_dic["nw_bw"]                              = LOG_CAT_L7VSD_NETWORK_BANDWIDTH;
2744         logcategory_string_dic[LOG_CAT_L7VSD_NETWORK_BANDWIDTH]      = "l7vsd_network_bandwidth";
2745         string_logcategory_dic["l7vsd_network_num_connection"]       = LOG_CAT_L7VSD_NETWORK_NUM_CONNECTION;
2746         string_logcategory_dic["nw_conn"]                            = LOG_CAT_L7VSD_NETWORK_NUM_CONNECTION;
2747         logcategory_string_dic[LOG_CAT_L7VSD_NETWORK_NUM_CONNECTION] = "l7vsd_network_num_connection";
2748         string_logcategory_dic["l7vsd_network_access"]               = LOG_CAT_L7VSD_NETWORK_ACCESS;
2749         string_logcategory_dic["nw_acc"]                             = LOG_CAT_L7VSD_NETWORK_ACCESS;
2750         logcategory_string_dic[LOG_CAT_L7VSD_NETWORK_ACCESS]         = "l7vsd_network_access";
2751         string_logcategory_dic["l7vsd_mainthread"]                   = LOG_CAT_L7VSD_MAINTHREAD;
2752         string_logcategory_dic["mth"]                                = LOG_CAT_L7VSD_MAINTHREAD;
2753         logcategory_string_dic[LOG_CAT_L7VSD_MAINTHREAD]             = "l7vsd_mainthread";
2754         string_logcategory_dic["l7vsd_virtualservice"]               = LOG_CAT_L7VSD_VIRTUALSERVICE;
2755         string_logcategory_dic["vs"]                                 = LOG_CAT_L7VSD_VIRTUALSERVICE;
2756         logcategory_string_dic[LOG_CAT_L7VSD_VIRTUALSERVICE]         = "l7vsd_virtualservice";
2757         string_logcategory_dic["l7vsd_virtualservice_thread"]        = LOG_CAT_L7VSD_VIRTUALSERVICE_THREAD;
2758         string_logcategory_dic["vs_th"]                              = LOG_CAT_L7VSD_VIRTUALSERVICE_THREAD;
2759         logcategory_string_dic[LOG_CAT_L7VSD_VIRTUALSERVICE_THREAD]  = "l7vsd_virtualservice_thread";
2760         string_logcategory_dic["l7vsd_session"]                      = LOG_CAT_L7VSD_SESSION;
2761         string_logcategory_dic["ss"]                                 = LOG_CAT_L7VSD_SESSION;
2762         logcategory_string_dic[LOG_CAT_L7VSD_SESSION]                = "l7vsd_session";
2763         string_logcategory_dic["l7vsd_session_thread"]               = LOG_CAT_L7VSD_SESSION_THREAD;
2764         string_logcategory_dic["ss_th"]                              = LOG_CAT_L7VSD_SESSION_THREAD;
2765         logcategory_string_dic[LOG_CAT_L7VSD_SESSION_THREAD]         = "l7vsd_session_thread";
2766         string_logcategory_dic["l7vsd_realserver"]                   = LOG_CAT_L7VSD_REALSERVER;
2767         string_logcategory_dic["rs"]                                 = LOG_CAT_L7VSD_REALSERVER;
2768         logcategory_string_dic[LOG_CAT_L7VSD_REALSERVER]             = "l7vsd_realserver";
2769         string_logcategory_dic["l7vsd_sorryserver"]                  = LOG_CAT_L7VSD_SORRYSERVER;
2770         string_logcategory_dic["sorry"]                              = LOG_CAT_L7VSD_SORRYSERVER;
2771         logcategory_string_dic[LOG_CAT_L7VSD_SORRYSERVER]            = "l7vsd_sorryserver";
2772         string_logcategory_dic["l7vsd_module"]                       = LOG_CAT_L7VSD_MODULE;
2773         string_logcategory_dic["mod"]                                = LOG_CAT_L7VSD_MODULE;
2774         logcategory_string_dic[LOG_CAT_L7VSD_MODULE]                 = "l7vsd_module";
2775         string_logcategory_dic["l7vsd_replication"]                  = LOG_CAT_L7VSD_REPLICATION;
2776         string_logcategory_dic["rep"]                                = LOG_CAT_L7VSD_REPLICATION;
2777         logcategory_string_dic[LOG_CAT_L7VSD_REPLICATION]            = "l7vsd_replication";
2778         string_logcategory_dic["l7vsd_replication_sendthread"]       = LOG_CAT_L7VSD_REPLICATION_SENDTHREAD;
2779         string_logcategory_dic["rep_sth"]                            = LOG_CAT_L7VSD_REPLICATION_SENDTHREAD;
2780         logcategory_string_dic[LOG_CAT_L7VSD_REPLICATION_SENDTHREAD] = "l7vsd_replication_sendthread";
2781         string_logcategory_dic["l7vsd_parameter"]                    = LOG_CAT_L7VSD_PARAMETER;
2782         string_logcategory_dic["para"]                               = LOG_CAT_L7VSD_PARAMETER;
2783         logcategory_string_dic[LOG_CAT_L7VSD_PARAMETER]              = "l7vsd_parameter";
2784         string_logcategory_dic["l7vsd_logger"]                       = LOG_CAT_L7VSD_LOGGER;
2785         string_logcategory_dic["logger"]                             = LOG_CAT_L7VSD_LOGGER;
2786         logcategory_string_dic[LOG_CAT_L7VSD_LOGGER]                 = "l7vsd_logger";
2787         string_logcategory_dic["l7vsd_command"]                      = LOG_CAT_L7VSD_COMMAND;
2788         string_logcategory_dic["cmd"]                                = LOG_CAT_L7VSD_COMMAND;
2789         logcategory_string_dic[LOG_CAT_L7VSD_COMMAND]                = "l7vsd_command";
2790         string_logcategory_dic["l7vsd_start_stop"]                   = LOG_CAT_L7VSD_START_STOP;
2791         string_logcategory_dic["stastp"]                             = LOG_CAT_L7VSD_START_STOP;
2792         logcategory_string_dic[LOG_CAT_L7VSD_START_STOP]             = "l7vsd_start_stop";
2793         string_logcategory_dic["l7vsd_system"]                       = LOG_CAT_L7VSD_SYSTEM;
2794         string_logcategory_dic["sys"]                                = LOG_CAT_L7VSD_SYSTEM;
2795         logcategory_string_dic[LOG_CAT_L7VSD_SYSTEM]                 = "l7vsd_system";
2796         string_logcategory_dic["l7vsd_system_memory"]                = LOG_CAT_L7VSD_SYSTEM_MEMORY;
2797         string_logcategory_dic["sys_mem"]                            = LOG_CAT_L7VSD_SYSTEM_MEMORY;
2798         logcategory_string_dic[LOG_CAT_L7VSD_SYSTEM_MEMORY]          = "l7vsd_system_memory";
2799         string_logcategory_dic["l7vsd_system_endpoint"]              = LOG_CAT_L7VSD_SYSTEM_ENDPOINT;
2800         string_logcategory_dic["sys_ep"]                             = LOG_CAT_L7VSD_SYSTEM_ENDPOINT;
2801         logcategory_string_dic[LOG_CAT_L7VSD_SYSTEM_ENDPOINT]        = "l7vsd_system_endpoint";
2802         string_logcategory_dic["l7vsd_system_signal"]                = LOG_CAT_L7VSD_SYSTEM_SIGNAL;
2803         string_logcategory_dic["sys_sig"]                            = LOG_CAT_L7VSD_SYSTEM_SIGNAL;
2804         logcategory_string_dic[LOG_CAT_L7VSD_SYSTEM_SIGNAL]          = "l7vsd_system_signal";
2805         string_logcategory_dic["l7vsd_system_environment"]           = LOG_CAT_L7VSD_SYSTEM_ENVIRONMENT;
2806         string_logcategory_dic["sys_env"]                            = LOG_CAT_L7VSD_SYSTEM_ENVIRONMENT;
2807         logcategory_string_dic[LOG_CAT_L7VSD_SYSTEM_ENVIRONMENT]     = "l7vsd_system_environment";
2808         string_logcategory_dic["l7vsd_snmpagent"]                    = LOG_CAT_L7VSD_SNMPAGENT;
2809         string_logcategory_dic["agent"]                              = LOG_CAT_L7VSD_SNMPAGENT;
2810         logcategory_string_dic[LOG_CAT_L7VSD_SNMPAGENT]              = "l7vsd_snmpagent";
2811         string_logcategory_dic["l7vsd_protocol"]                     = LOG_CAT_PROTOCOL;
2812         string_logcategory_dic["prot"]                               = LOG_CAT_PROTOCOL;
2813         logcategory_string_dic[LOG_CAT_PROTOCOL]                     = "l7vsd_protocol";
2814         string_logcategory_dic["l7vsd_schedule"]                     = LOG_CAT_SCHEDULE;
2815         string_logcategory_dic["sched"]                              = LOG_CAT_SCHEDULE;
2816         logcategory_string_dic[LOG_CAT_SCHEDULE]                     = "l7vsd_schedule";
2817         string_logcategory_dic["all"]                                = LOG_CAT_END;
2818
2819         // string log level dictionary create.
2820         string_loglevel_dic["debug"]      = LOG_LV_DEBUG;
2821         loglevel_string_dic[LOG_LV_DEBUG] = "debug";
2822         string_loglevel_dic["info"]       = LOG_LV_INFO;
2823         loglevel_string_dic[LOG_LV_INFO]  = "info";
2824         string_loglevel_dic["warn"]       = LOG_LV_WARN;
2825         loglevel_string_dic[LOG_LV_WARN]  = "warn";
2826         string_loglevel_dic["error"]      = LOG_LV_ERROR;
2827         loglevel_string_dic[LOG_LV_ERROR] = "error";
2828         string_loglevel_dic["fatal"]      = LOG_LV_FATAL;
2829         loglevel_string_dic[LOG_LV_FATAL] = "fatal";
2830
2831         // parameter category dictionary create
2832         string_parameter_dic["all"]            = PARAM_COMP_ALL;
2833         string_parameter_dic["l7vsd"]          = PARAM_COMP_L7VSD;
2834         string_parameter_dic["command"]        = PARAM_COMP_COMMAND;
2835         string_parameter_dic["session"]        = PARAM_COMP_SESSION;
2836         string_parameter_dic["virtualservice"] = PARAM_COMP_VIRTUALSERVICE;
2837         string_parameter_dic["module"]         = PARAM_COMP_MODULE;
2838         string_parameter_dic["replication"]    = PARAM_COMP_REPLICATION;
2839         string_parameter_dic["logger"]         = PARAM_COMP_LOGGER;
2840         string_parameter_dic["l7vsadm"]        = PARAM_COMP_L7VSADM;
2841         string_parameter_dic["snmpagent"]      = PARAM_COMP_SNMPAGENT;
2842         string_parameter_dic["ssl"]            = PARAM_COMP_SSL;
2843
2844         // create disp_result dictionary.
2845         disp_result_dic[l7vsadm_request::CMD_LIST]         = boost::bind(&l7vsadm::disp_list, this);
2846         disp_result_dic[l7vsadm_request::CMD_LIST_KEY]     = boost::bind(&l7vsadm::disp_list_key, this);
2847         disp_result_dic[l7vsadm_request::CMD_LIST_VERBOSE] = boost::bind(&l7vsadm::disp_list_verbose, this);
2848
2849         // response_message_dic create
2850         response_error_message_dic[l7vsd_response::RESPONSE_ERROR]              = "command error : ";
2851         response_error_message_dic[l7vsd_response::RESPONSE_LIST_ERROR]         = "list command error : ";
2852         response_error_message_dic[l7vsd_response::RESPONSE_LIST_VERBOSE_ERROR] = "list verbose error : ";
2853         response_error_message_dic[l7vsd_response::RESPONSE_LIST_KEY_ERROR]     = "list key error : ";
2854         response_error_message_dic[l7vsd_response::RESPONSE_ADD_VS_ERROR]       = "add vs error : ";
2855         response_error_message_dic[l7vsd_response::RESPONSE_DEL_VS_ERROR]       = "del vs error : ";
2856         response_error_message_dic[l7vsd_response::RESPONSE_EDIT_VS_ERROR]      = "edit vs error : ";
2857         response_error_message_dic[l7vsd_response::RESPONSE_FLUSH_VS_ERROR]     = "flush vs error : ";
2858         response_error_message_dic[l7vsd_response::RESPONSE_ADD_RS_ERROR]       = "add rs error : ";
2859         response_error_message_dic[l7vsd_response::RESPONSE_DEL_RS_ERROR]       = "del rs error : ";
2860         response_error_message_dic[l7vsd_response::RESPONSE_EDIT_RS_ERROR]      = "edit rs error : ";
2861         response_error_message_dic[l7vsd_response::RESPONSE_REPLICATION_ERROR]  = "replication command error : ";
2862         response_error_message_dic[l7vsd_response::RESPONSE_LOG_ERROR]          = "log command error : ";
2863         response_error_message_dic[l7vsd_response::RESPONSE_SNMP_ERROR]         = "snmp command error : ";
2864         response_error_message_dic[l7vsd_response::RESPONSE_PARAMETER_ERROR]    = "parameter error : ";
2865
2866         replication_mode_string_dic[replication::REPLICATION_OUT]         = "OUT";
2867         replication_mode_string_dic[replication::REPLICATION_SINGLE]      = "SINGLE";
2868         replication_mode_string_dic[replication::REPLICATION_MASTER]      = "MASTER";
2869         replication_mode_string_dic[replication::REPLICATION_SLAVE]       = "SLAVE";
2870         replication_mode_string_dic[replication::REPLICATION_MASTER_STOP] = "MASTER_STOP";
2871         replication_mode_string_dic[replication::REPLICATION_SLAVE_STOP]  = "SLAVE_STOP";
2872 }
2873
2874 //! Get l7vsadm parameter data
2875 void l7vs::l7vsadm::set_parameter()
2876 {
2877         Logger logger(LOG_CAT_L7VSADM_COMMON, 36, "l7vsadm::set_parameter", __FILE__, __LINE__);
2878
2879         // Get and Set l7vsadm all parameter value.
2880         Parameter param;
2881         error_code err;
2882
2883         // command_wait_interval
2884         command_wait_interval = param.get_int(PARAM_COMP_L7VSADM, "cmd_interval", err);
2885         if (!err) {
2886                 if (command_wait_interval < 0 ||
2887                     command_wait_interval > L7VSADM_MAX_WAIT) {
2888                         // When illegal parameter value, use default parameter value.
2889                         command_wait_interval = L7VSADM_DEFAULT_WAIT_INTERVAL;
2890                         std::stringstream msg;
2891                         msg << boost::format("Illegal cmd_interval parameter value. Use default value(%s).")
2892                             % L7VSADM_DEFAULT_WAIT_INTERVAL;
2893                         Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 1, msg.str(), __FILE__, __LINE__);
2894                 }
2895         } else {
2896                 command_wait_interval = L7VSADM_DEFAULT_WAIT_INTERVAL;
2897                 std::stringstream msg;
2898                 msg << boost::format("Get cmd_interval parameter error. Use default value(%s).")
2899                     % L7VSADM_DEFAULT_WAIT_INTERVAL;
2900                 Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 2, msg.str(), __FILE__, __LINE__);
2901         }
2902
2903         //command_wait_count
2904         command_wait_count = param.get_int(PARAM_COMP_L7VSADM, "cmd_count", err);
2905         if (!err) {
2906                 if (command_wait_count < 0 ||
2907                     command_wait_count > L7VSADM_MAX_WAIT) {
2908                         // When illegal parameter value, use default parameter value.
2909                         command_wait_count = L7VSADM_DEFAULT_WAIT_COUNT;
2910                         std::stringstream msg;
2911                         msg << boost::format("Illegal cmd_count parameter value. Use default value(%s).")
2912                             % L7VSADM_DEFAULT_WAIT_COUNT;
2913                         Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 3, msg.str(), __FILE__, __LINE__);
2914                 }
2915         } else {
2916                 command_wait_count = L7VSADM_DEFAULT_WAIT_COUNT;
2917                 std::stringstream msg;
2918                 msg << boost::format("Get cmd_count parameter error. Use default value(%s).")
2919                     % L7VSADM_DEFAULT_WAIT_COUNT;
2920                 Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 4, msg.str(), __FILE__, __LINE__);
2921         }
2922
2923         if ((command_wait_interval * command_wait_count) > L7VSADM_MAX_WAIT) {
2924                 // When wait value too long, use default parameter value.
2925                 command_wait_interval = L7VSADM_DEFAULT_WAIT_INTERVAL;
2926                 command_wait_count = L7VSADM_DEFAULT_WAIT_COUNT;
2927                 std::stringstream msg;
2928                 msg << boost::format("Command wait value too long. Use default value(%s).")
2929                     % L7VSADM_DEFAULT_WAIT_COUNT;
2930                 Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 9, msg.str(), __FILE__, __LINE__);
2931         }
2932 }
2933
2934 //! l7vsadm command execute
2935 bool l7vs::l7vsadm::execute(int argc, char *argv[])
2936 {
2937         Logger logger(LOG_CAT_L7VSADM_COMMON, 37, "l7vsadm::execute", __FILE__, __LINE__);
2938
2939         /*-------- DEBUG LOG --------*/
2940         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSADM_COMMON)) {
2941                 std::stringstream debugstr;
2942                 debugstr << boost::format("l7vsadm::execute arguments: %s") % argument_debug_dump(argc, argv);
2943                 Logger::putLogDebug(LOG_CAT_L7VSADM_COMMON, 38, debugstr.str(), __FILE__, __LINE__);
2944         }
2945         /*------ DEBUG LOG END ------*/
2946
2947         // set sighandler
2948         if (0 > set_sighandlers()) {
2949                 std::string buf("set_sighandlers failed.");
2950                 std::cerr << "COMMON ERROR: " << buf << std::endl;
2951                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 1, buf, __FILE__, __LINE__);
2952                 return false;
2953         }
2954
2955         // read param
2956         set_parameter();
2957
2958         // Get l7vsadm execute file path from /proc/(pid)/exe (symbolic link)
2959         char l7vsadm_file_path[256];
2960         ssize_t retsize;
2961         memset(l7vsadm_file_path, 0, sizeof(l7vsadm_file_path));
2962         retsize = readlink("/proc/self/exe", l7vsadm_file_path, sizeof(l7vsadm_file_path));
2963
2964         // L7vsadm command conflict check. (Try l7vsadm execute file lock)
2965         file_lock lock(l7vsadm_file_path, l7vsadm_err);
2966         if (l7vsadm_err) {
2967                 std::cerr << "COMMON ERROR: " << l7vsadm_err.get_message() << std::endl;
2968                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 2, l7vsadm_err.get_message(), __FILE__, __LINE__);
2969                 return false;
2970         }
2971
2972         try {
2973                 // l7vsadm file lock wait
2974                 int command_retry_count = 0;
2975                 while (true) {
2976                         // Check signal.
2977                         if (signal_flag) {
2978                                 std::stringstream buf;
2979                                 buf << boost::format("Signal (%d) Received.") % received_sig;
2980                                 l7vsadm_err.setter(true, buf.str());
2981                                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 3, buf.str(), __FILE__, __LINE__);
2982                                 break;
2983                         }
2984
2985                         // Try lock l7vsadm file.
2986                         if (lock.try_lock()) {
2987                                 break;
2988                         }
2989
2990                         ++command_retry_count;
2991                         if (command_retry_count > command_wait_count) {
2992                                 // L7vsadm file lock error. (l7vsadm is executing)
2993                                 std::string buf("L7vsadm file lock timeout. (l7vsadm is already executing)");
2994                                 l7vsadm_err.setter(true, buf);
2995                                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 4, buf, __FILE__, __LINE__);
2996                                 break;
2997                         }
2998
2999                         std::stringstream buf;
3000                         buf << boost::format("L7vsadm file lock error. (l7vsadm is already executing) (retry %d)") % command_retry_count;
3001                         Logger::putLogWarn(LOG_CAT_L7VSADM_COMMON, 11, buf.str(), __FILE__, __LINE__);
3002
3003                         // Lock retrying.
3004                         boost::xtime xt;
3005                         xtime_get(&xt, boost::TIME_UTC);
3006                         xt.sec += command_wait_interval;
3007                         boost::thread::sleep(xt);
3008                 }
3009
3010                 // display err
3011                 if (l7vsadm_err) {
3012                         std::cerr << "COMMON ERROR: " << l7vsadm_err.get_message() << std::endl;
3013                         return false;
3014                 }
3015
3016                 // no argument, assume list command
3017                 if (1 == argc) {
3018                         request.command = l7vsadm_request::CMD_LIST;
3019                 } else {
3020                         // parse command line
3021                         int pos = 1;
3022                         parse_cmd_map_type::iterator itr = command_dic.find(argv[pos]);
3023                         if (itr != command_dic.end()) {
3024                                 itr->second(argc, argv);
3025                         } else {
3026                                 std::string buf("command not found.");
3027                                 l7vsadm_err.setter(true, buf);
3028                                 Logger::putLogError(LOG_CAT_L7VSADM_PARSE, 88, buf, __FILE__, __LINE__);
3029                         }
3030                 }
3031
3032                 // display command parse result
3033                 if (l7vsadm_err) {
3034                         std::cerr << "PARSE ERROR: " << l7vsadm_err.get_message() << std::endl;
3035                         std::cerr << usage() << std::endl;
3036                         return false;
3037                 }
3038
3039                 if (l7vsadm_request::CMD_HELP != request.command) {
3040                         // communicate to l7vsd
3041                         using boost::asio::local::stream_protocol;
3042                         boost::array<char, COMMAND_BUFFER_SIZE> response_buffer;
3043                         response_buffer.assign(0x00);
3044
3045                         // connect
3046                         boost::asio::io_service io;
3047                         stream_protocol::socket s(io);
3048
3049                         // Check signal.
3050                         if (signal_flag) {
3051                                 std::stringstream buf;
3052                                 buf << boost::format("Signal (%d) Received.") % received_sig;
3053                                 l7vsadm_err.setter(true, buf.str());
3054                                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 5, buf.str(), __FILE__, __LINE__);
3055                         } else {
3056                                 // Try connect to config socket.
3057                                 boost::system::error_code err;
3058                                 s.connect(stream_protocol::endpoint(L7VS_CONFIG_SOCKNAME), err);
3059                                 if (err) {
3060                                         std::stringstream buf;
3061                                         buf << boost::format("connect() failed: %s.") % err.message();
3062                                         l7vsadm_err.setter(true, buf.str());
3063                                         Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 9, buf.str(), __FILE__, __LINE__);
3064                                 }
3065                         }
3066
3067                         // display err
3068                         if (l7vsadm_err) {
3069                                 std::cerr << "COMMON ERROR: " << l7vsadm_err.get_message() << std::endl;
3070                                 return false;
3071                         }
3072
3073                         /*-------- DEBUG LOG --------*/
3074                         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSADM_COMMON)) {
3075                                 std::stringstream debugstr;
3076                                 debugstr << boost::format("l7vsadm_send_request:%s") % request;
3077                                 Logger::putLogDebug(LOG_CAT_L7VSADM_COMMON, 39, debugstr.str(), __FILE__, __LINE__);
3078                         }
3079                         /*------ DEBUG LOG END ------*/
3080
3081                         // write sockfile
3082                         std::stringstream send_stream;
3083                         boost::archive::text_oarchive oa(send_stream);
3084                         oa << (const l7vs::l7vsadm_request &) request;
3085                         boost::asio::write(s, boost::asio::buffer(send_stream.str()));
3086
3087                         // read sockfile
3088                         s.read_some(boost::asio::buffer(response_buffer));
3089
3090                         std::stringstream recv_stream;
3091                         recv_stream << &(response_buffer[0]);
3092                         boost::archive::text_iarchive ia(recv_stream);
3093                         ia >> response;
3094
3095                         /*-------- DEBUG LOG --------*/
3096                         if (LOG_LV_DEBUG == Logger::getLogLevel(LOG_CAT_L7VSADM_COMMON)) {
3097                                 std::stringstream debugstr;
3098                                 debugstr << boost::format("l7vsadm_recv_response:%s") % response;
3099                                 Logger::putLogDebug(LOG_CAT_L7VSADM_COMMON, 40, debugstr.str(), __FILE__, __LINE__);
3100                         }
3101                         /*------ DEBUG LOG END ------*/
3102
3103                         // close socket
3104                         s.close();
3105
3106                         // display result
3107                         if (l7vsd_response::RESPONSE_OK == response.status) {
3108                                 disp_result_map_type::iterator itr = disp_result_dic.find(request.command);
3109                                 if (itr != disp_result_dic.end())
3110                                         itr->second();
3111                         } else {
3112                                 std::stringstream buf;
3113                                 response_error_message_map_type::iterator itr = response_error_message_dic.find(response.status);
3114                                 if (itr != response_error_message_dic.end())
3115                                         buf << itr->second << response.message;
3116                                 else
3117                                         buf << "COMMAND ERROR: " << response.message;
3118                                 std::cerr << buf.str() << std::endl;
3119                                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 7, buf.str(), __FILE__, __LINE__);
3120                                 return false;
3121                         }
3122                 } //if help_mode
3123         } //try
3124         catch (std::exception &e) {
3125                 std::stringstream buf;
3126                 buf << "COMMON ERROR: " << e.what();
3127                 std::cerr << buf.str() << std::endl;
3128                 Logger::putLogError(LOG_CAT_L7VSADM_COMMON, 8, buf.str(), __FILE__, __LINE__);
3129                 return false;
3130         }
3131         return true;
3132 }
3133
3134 //! argument dump for debug
3135 //! @param[in] argument count
3136 //! @param[in] argument value
3137 std::string l7vs::l7vsadm::argument_debug_dump(int argc, char *argv[])
3138 {
3139         std::stringstream buf;
3140         if (!argv) {
3141                 buf << "argument=(null)";
3142         } else {
3143                 buf << boost::format("argument={argc=%d") % argc;
3144                 for (int i = 0; i < argc; ++i) {
3145                         buf << boost::format(", argv[%d]=%s") % i % argv[i];
3146                 }
3147                 buf << "}";
3148         }
3149         return buf.str();
3150 }
3151
3152 //! signal handler function
3153 //! @param[in] signal
3154 static void sig_exit_handler(int sig)
3155 {
3156         received_sig = sig;
3157         signal_flag = true;
3158 }
3159
3160 //! set signal handler function
3161 //! @param[in] signal
3162 //! @param[in] handler function pointer
3163 //! @return 0/success, -1/fail
3164 static int set_sighandler(int sig, void (*handler)(int))
3165 {
3166         struct sigaction act;
3167         int ret;
3168
3169         ret = sigaction(sig, NULL, &act);
3170         if (0 > ret) {
3171                 return ret;
3172         }
3173
3174         act.sa_flags &= ~SA_RESETHAND;
3175         act.sa_handler = handler;
3176
3177         ret = sigaction(sig, &act, NULL);
3178         if (0 > ret) {
3179                 return ret;
3180         }
3181
3182         return 0;
3183 }
3184
3185 //! set all signal handler function
3186 //! @return 0/success, -1/fail
3187 static int set_sighandlers()
3188 {
3189         int ret;
3190
3191 #define SET_SIGHANDLER(sig, handler)            \
3192     do {                                        \
3193         ret = set_sighandler((sig), (handler)); \
3194         if (ret < 0) {                          \
3195             return ret;                         \
3196         }                                       \
3197     } while (0)
3198
3199         SET_SIGHANDLER(SIGHUP,  sig_exit_handler);
3200         SET_SIGHANDLER(SIGINT,  sig_exit_handler);
3201         SET_SIGHANDLER(SIGQUIT, sig_exit_handler);
3202         SET_SIGHANDLER(SIGPIPE, sig_exit_handler);
3203         SET_SIGHANDLER(SIGTERM, sig_exit_handler);
3204         SET_SIGHANDLER(SIGUSR1, sig_exit_handler);
3205         SET_SIGHANDLER(SIGUSR2, sig_exit_handler);
3206
3207 #undef SET_SIGHANDLER
3208
3209         return 0;
3210 }
3211
3212 #ifndef UNIT_TEST
3213 int main(int argc, char *argv[])
3214 {
3215         try {
3216                 l7vs::Logger logger;
3217                 l7vs::Parameter param;
3218                 logger.loadConf();
3219         } catch (...) {
3220         }
3221
3222         l7vs::l7vsadm adm;
3223         if (!adm.execute(argc, argv)) {
3224                 return -1;
3225         }
3226         return 0;
3227 }
3228 #endif //UNIT_TEST