OSDN Git Service

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