OSDN Git Service

Module bug fix.
[ultramonkey-l7/ultramonkey-l7-v2.git] / module / protocol / protomod_pfilter.c
1 /*
2  * @file  protomod_pfilter.c
3  * @brief protocol module of HTTP.
4  * @brief this module provide session persistence by URL.
5  *
6  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7  * Copyright (C) 2008  NTT COMWARE Corporation.
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22  * 02110-1301 USA
23  *
24  **********************************************************************/
25
26 #define __STDC_LIMIT_MACROS
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <getopt.h>
32 #include "l7vs_service.h"
33 #include "l7vs_conn.h"
34 #include "l7vs_dest.h"
35 #include "l7vs_module.h"
36 #include <fnmatch.h>
37
38 #include <iostream>
39 #ifdef USE_BOOST_XPRESSIVE
40     #include <boost/xpressive/xpressive.hpp>
41 #else
42     #include <boost/regex.hpp>
43 #endif
44
45 #define SERVICE_ARG_MAXSIZE    (512)
46 #define PATTERN_MATCH_MAXSIZE  (128)
47 #define URL_SERVICE_NUMBER     (128)
48 #define X_FORWARDED_FOR_LENGTH (48)
49
50 struct l7vs_pfilter_service {
51         handle_t service_handle;
52         char pattern_match[PATTERN_MATCH_MAXSIZE];
53         int read_byte;
54 #ifdef USE_BOOST_XPRESSIVE
55         boost::xpressive::sregex regex;
56 #else
57         boost::regex regex;
58 #endif
59         int reschedule;
60 };
61
62 struct  l7vs_pfilter_service_arg {
63         char pattern_match[PATTERN_MATCH_MAXSIZE];
64         int read_byte;
65         int reschedule;
66 };
67
68 static void  fini(void);
69 static int   create(void*, handle_t);
70 static void* create_sa(struct l7vs_service_arg*);
71 static int   compare(handle_t, handle_t);
72 static int   select_dest(struct l7vs_service*, struct l7vs_conn*,
73         char*, size_t*, struct l7vs_dest**);
74 static int   analyze_cldata(struct l7vs_service*, struct l7vs_conn*,
75         char*, size_t*);
76 static int   analyze_rsdata(struct l7vs_service*, struct l7vs_conn*,
77         char*, size_t*);
78 static int   destroy(handle_t);
79 static void  destroy_sa(void**);
80 static int   service_arg(struct l7vs_service_arg_multi*, handle_t);
81 static int   parse(void*, int, char**);
82
83 static struct l7vs_pfilter_service *l7vs_protomod_pfilter_search_service(handle_t);
84 static struct l7vs_pfilter_service *l7vs_protomod_pfilter_create_service();
85 static struct l7vs_pfilter_service *l7vs_protomod_pfilter_create_temp_service();
86
87 static void l7vs_pfilter_service_c_str(char*, struct l7vs_pfilter_service*);
88 static void l7vs_pfilter_service_arg_c_str(char*, struct l7vs_pfilter_service_arg*);
89
90 struct l7vs_pfilter_service *pfilter_service_list[URL_SERVICE_NUMBER];
91
92 static struct l7vs_protomod pfilter_protomod = {
93         NULL,           /* handle */
94         "pfilter",          /* modname */
95         0,              /* refcnt */
96         0,              /* fast schedule */
97         create,         /* create function */
98         compare,        /* compare function */
99         select_dest,    /* select_dest function */
100         analyze_cldata, /* analyze_cldata function */
101         analyze_rsdata, /* analyze_rsdata function */
102         destroy,        /* destroy function */
103         fini,           /* fini function */
104         create_sa,      /* create_sa function */
105         service_arg,    /* service_arg function */
106         parse,          /* parse function */
107         destroy_sa,     /* destroy_sa function */
108         NULL,           /* initialize function */
109         NULL,           /* finalize function */
110         NULL,           /* get_log_level function */
111         NULL,           /* put_log_debug function */
112         NULL,           /* put_log_info function */
113         NULL,           /* put_log_warn function */
114         NULL,           /* put_log_error function */
115         NULL            /* put_log_fatal function */
116 };
117
118 /*!
119  * Protocol module initialize function. This function run when dlopen and dlsym at first time.
120  * @param[in] handle dlopen's handle
121  * @return l7vs_protomod struct
122  */
123 extern "C" struct l7vs_protomod *
124 init(void *handle)
125 {
126         struct l7vs_protomod* return_value = NULL;
127
128         /*-------- DEBUG LOG --------*/
129         if (pfilter_protomod.get_log_level != NULL &&
130             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
131                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,283,
132                     "in_function: struct l7vs_protomod* init(void* handle): handle=%p", handle);
133         }
134         /*------ DEBUG LOG END ------*/
135
136         /* check null */
137         if (handle == NULL) {
138                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,246, "Arg(handle) is NULL pointer.");
139                 goto init_out;
140         }
141
142         /* initialize pfilter service list */
143         memset(pfilter_service_list, 0, sizeof(struct l7vs_pfilter_service *) * URL_SERVICE_NUMBER);
144         /* set dlopen's handle */
145         pfilter_protomod.handle = handle;
146
147         return_value = &pfilter_protomod;
148
149 init_out:
150         /*-------- DEBUG LOG --------*/
151         if (pfilter_protomod.get_log_level != NULL &&
152             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
153                 char protomod_str[DEBUG_STR_LEN] = {0};
154                 l7vs_protomod_c_str(protomod_str, &pfilter_protomod);
155                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,284,
156                     "out_function: struct l7vs_protomod* init(void* handle): return=&(%s)", protomod_str);
157         }
158         /*------ DEBUG LOG END ------*/
159         return return_value;
160 }
161
162 /*!
163  * Protocol module finalize function. free all pfilter service list just in case.
164  * @param   void
165  * @return  void
166  */
167 static void
168 fini(void)
169 {
170         /* pfilter service list counter */
171         int service_number = 0;
172
173         /*-------- DEBUG LOG --------*/
174         if (pfilter_protomod.get_log_level != NULL &&
175             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
176                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,285, "in_function: void fini(void)");
177         }
178         /*------ DEBUG LOG END ------*/
179
180         /* check all pfilter service list */
181         for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
182                 /* if pointer that does not point NULL exists ... */
183                 if (pfilter_service_list[service_number] != NULL) {
184
185                         /*-------- DEBUG LOG --------*/
186                         if (pfilter_protomod.get_log_level != NULL &&
187                             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
188                                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,63, "free: %p",
189                                     pfilter_service_list[service_number]);
190                         }
191                         /*------ DEBUG LOG END ------*/
192
193                         /* free and points NULL */
194                         free(pfilter_service_list[service_number]);
195                         pfilter_service_list[service_number] = NULL;
196                 }
197         }
198         /*-------- DEBUG LOG --------*/
199         if (pfilter_protomod.get_log_level != NULL &&
200             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
201                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,286, "out_function: void fini(void)");
202         }
203         /*------ DEBUG LOG END ------*/
204 }
205
206 /*!
207  * Create pfilter service struct.
208  * @param  pfilter_arg    pfilter service argument struct
209  * @param  service_handle a unique service ID
210  * @retval 0  successfully create pfilter service.
211  * @retval -1 some errors occur.
212  */
213 static int
214 create(void *pfilter_arg, handle_t service_handle)
215 {
216         struct l7vs_pfilter_service *pfilter_service;
217         struct l7vs_pfilter_service_arg *pfilter_service_arg;
218         int return_value = 0;
219
220         /*-------- DEBUG LOG --------*/
221         if (pfilter_protomod.get_log_level != NULL &&
222             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
223                 char pfilter_arg_str[DEBUG_STR_LEN] = {0};
224                 l7vs_pfilter_service_arg_c_str(pfilter_arg_str, (struct l7vs_pfilter_service_arg*) pfilter_arg);
225                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,287,
226                     "in_function: int create(void* pfilter_arg, handle_t service_handle):pfilter_arg=&(%s), "
227                     "service_handle=%d", pfilter_arg_str, service_handle);
228         }
229         /*------ DEBUG LOG END ------*/
230
231         /* check null */
232         if (pfilter_arg == NULL) {
233                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,247, "Arg(pfilter_arg) is NULL pointer.");
234                 return_value = -1;
235                 goto create_out;
236         }
237
238         if (service_handle != TEMP_SERVICEHANDLE) {
239                 /* search empty pfilter service list and create pfilter service */
240                 pfilter_service = l7vs_protomod_pfilter_create_service();
241         } else {
242                 /* create temporary pfilter service */
243                 pfilter_service = l7vs_protomod_pfilter_create_temp_service();
244         }
245
246         /*-------- DEBUG LOG --------*/
247         if (pfilter_protomod.get_log_level != NULL &&
248             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
249                 char pfilter_str[DEBUG_STR_LEN] = {0};
250                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_service);
251                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,288, "pointer assign: pfilter_service=&(%s)",
252                     pfilter_str);
253         }
254         /*------ DEBUG LOG END ------*/
255
256         if (pfilter_service == NULL) {
257                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,248, "Could not make pfilter service.");
258                 return_value = -1;
259                 goto create_out;
260         }
261
262         pfilter_service_arg = (struct l7vs_pfilter_service_arg *) pfilter_arg;
263
264         /* set service handle, pattern match and reschedule flag */
265         pfilter_service->service_handle = service_handle;
266         strncpy(pfilter_service->pattern_match, pfilter_service_arg->pattern_match, PATTERN_MATCH_MAXSIZE);
267         pfilter_service->read_byte = pfilter_service_arg->read_byte;
268         if (pfilter_service_arg->pattern_match) {
269                 try {
270 #ifdef USE_BOOST_XPRESSIVE
271                         pfilter_service->regex = boost::xpressive::sregex::compile(pfilter_service_arg->pattern_match);
272 #else
273                         pfilter_service->regex.assign(pfilter_service_arg->pattern_match);
274 #endif
275                 }
276                 catch (...) {
277                         PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,249, "Regex pattern error.");
278                         return_value = -1;
279                         goto create_out;
280                 }
281         }
282         pfilter_service->reschedule = pfilter_service_arg->reschedule;
283
284 create_out:
285         /*-------- DEBUG LOG --------*/
286         if (pfilter_protomod.get_log_level != NULL &&
287             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
288                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,289,
289                     "out_function: int create(void* pfilter_arg, handle_t service_handle):return_value=%d",
290                     return_value);
291         }
292         /*------ DEBUG LOG END ------*/
293
294         return return_value;
295 }
296
297 /*!
298  * Create pfilter service argument struct.
299  * @param[out] srv_arg service argument struct
300  * @return pfilter service argument struct
301  */
302 static void *
303 create_sa(struct l7vs_service_arg *srv_arg)
304 {
305         struct l7vs_pfilter_service_arg *pfilter_service_arg;
306
307         /*-------- DEBUG LOG --------*/
308         if (pfilter_protomod.get_log_level != NULL &&
309             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
310                 char service_arg_str[DEBUG_STR_LEN] = {0};
311                 l7vs_service_arg_c_str(service_arg_str, srv_arg);
312                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,290,
313                     "in_function: void* create_sa(struct l7vs_service_arg* srv_arg):srv_arg=&(%s)",
314                     service_arg_str);
315         }
316         /*------ DEBUG LOG END ------*/
317
318         /* check null */
319         if (srv_arg == NULL) {
320                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,250, "Arg(srv_arg) is NULL pointer.");
321                 pfilter_service_arg = NULL;
322                 goto create_sa_out;
323         }
324
325         /* create pfilter service argument struct */
326         pfilter_service_arg = (struct l7vs_pfilter_service_arg *) calloc(1, sizeof(struct l7vs_pfilter_service_arg));
327
328         /*-------- DEBUG LOG --------*/
329         if (pfilter_protomod.get_log_level != NULL &&
330             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
331                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,64, "calloc: addr=%p, size=%ld",
332                     pfilter_service_arg, (unsigned long int) sizeof(struct l7vs_pfilter_service_arg));
333         }
334         /*------ DEBUG LOG END ------*/
335
336         if (pfilter_service_arg == NULL) {
337                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,56, "Could not allocate memory.");
338                 goto create_sa_out;
339         }
340
341         /* set pfilter service argument size and protomod name "pfilter" */
342         srv_arg->len = sizeof(struct l7vs_pfilter_service_arg);
343         strcpy(srv_arg->protomod, pfilter_protomod.modname);
344
345 create_sa_out:
346         /*-------- DEBUG LOG --------*/
347         if (pfilter_protomod.get_log_level != NULL &&
348             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
349                 char pfilter_service_arg_str[DEBUG_STR_LEN] = {0};
350                 l7vs_pfilter_service_arg_c_str(pfilter_service_arg_str, pfilter_service_arg);
351                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,291,
352                     "out_function: void* create_sa(struct l7vs_service_arg* srv_arg):return_value=&(%s)",
353                     pfilter_service_arg_str);
354         }
355         /*------ DEBUG LOG END ------*/
356
357         return (void*) pfilter_service_arg;
358 }
359
360 /*!
361  * Compare two service.
362  * @param[in] srv_handle1 one of a unique service ID
363  * @param[in] srv_handle2 one of a unique service ID
364  * @retval 0  they matched perfectly.
365  * @retval -1 they are different.
366  */
367 static int
368 compare(handle_t srv_handle1, handle_t srv_handle2)
369 {
370         struct l7vs_pfilter_service *pfilter_srv1, *pfilter_srv2;
371         int return_value = 0;
372
373         /*-------- DEBUG LOG --------*/
374         if (pfilter_protomod.get_log_level != NULL &&
375             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
376                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,292,
377                     "in_function: int compare(handle_t srv_handle1, handle_t srv_handle2):"
378                     "srv_handle1=%u, srv_handle2=%u", srv_handle1, srv_handle2);
379         }
380         /*------ DEBUG LOG END ------*/
381
382         /* search service that has such a service ID(1) */
383         pfilter_srv1 = l7vs_protomod_pfilter_search_service(srv_handle1);
384
385         /*-------- DEBUG LOG --------*/
386         if (pfilter_protomod.get_log_level != NULL &&
387             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
388                 char pfilter_str[DEBUG_STR_LEN] = {0};
389                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_srv1);
390                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,293, "pointer assign: pfilter_srv1=&(%s)",
391                     pfilter_str);
392         }
393         /*------ DEBUG LOG END ------*/
394
395         if (pfilter_srv1 == NULL) {
396                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,251,
397                     "Could not find such service handle's pfilter service.");
398                 return_value = -1;
399                 goto compare_out;
400         }
401
402         /* search service that has such a service ID(2) */
403         pfilter_srv2 = l7vs_protomod_pfilter_search_service(srv_handle2);
404
405         /*-------- DEBUG LOG --------*/
406         if (pfilter_protomod.get_log_level != NULL &&
407             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
408                 char pfilter_str[DEBUG_STR_LEN] = {0};
409                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_srv2);
410                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,294, "pointer assign: pfilter_srv2=&(%s)",
411                     pfilter_str);
412         }
413         /*------ DEBUG LOG END ------*/
414
415         if (pfilter_srv2 == NULL) {
416                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,252,
417                     "Could not find such service handle's pfilter service.");
418                 return_value = -1;
419                 goto compare_out;
420         }
421
422         /* compare two pattern match */
423         if (strcmp(pfilter_srv1->pattern_match, pfilter_srv2->pattern_match) != 0) {
424                 return_value = -1;
425                 goto compare_out;
426         }
427
428 compare_out:
429         /*-------- DEBUG LOG --------*/
430         if (pfilter_protomod.get_log_level != NULL &&
431             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
432                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,295,
433                     "out_function: int compare(handle_t srv_handle1, handle_t srv_handle2):return_value=%d",
434                     return_value);
435         }
436         /*------ DEBUG LOG END ------*/
437
438         return return_value;
439 }
440
441 /*!
442  * Determine a real server.
443  * @param[in]  srv service struct include service handle, protocol module and schedule module.
444  * @param[in]  conn connection data.
445  * @param[in]  request packet data from client
446  * @param[in]  len length of packet data
447  * @param[out] dest destination (real server) list
448  * @retval 0  successfully check packet data
449  * @retval -1 some errors occur.
450  */
451 static int
452 select_dest(struct l7vs_service *srv, struct l7vs_conn *conn,
453       char *request, size_t *len, struct l7vs_dest **dest)
454 {
455         struct l7vs_pfilter_service *pfilter_service;
456         int ret;
457         int return_value = 0;
458     std::string packet_data;
459
460         /*-------- DEBUG LOG --------*/
461         if (pfilter_protomod.get_log_level != NULL &&
462             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
463                 char srv_str[DEBUG_STR_LEN] = {0};
464                 char conn_str[DEBUG_STR_LEN] = {0};
465                 char dest_str[DEBUG_STR_LEN] = {0};
466                 char len_str[DEBUG_STR_LEN] = {0};
467                 l7vs_service_c_str(srv_str, srv);
468                 l7vs_conn_c_str(conn_str, conn);
469                 if (dest != NULL) {
470                         l7vs_dest_c_str(dest_str, *dest);
471                 }
472                 else {
473                         strncpy(dest_str, "NULL", DEBUG_STR_LEN);
474                 }
475                 if (len != NULL) {
476                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
477                 }
478                 else {
479                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
480                 }
481                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,296,
482                     "in_function: int select_dest(struct l7vs_service* srv, struct l7vs_conn* conn, "
483                     "char* request, size_t* len, struct l7vs_dest** dest):srv=&(%s), conn=&(%s), "
484                     "request=\"%s\", len=&(%s), dest=&(&(%s))",
485                     srv_str, conn_str, request, len_str, dest_str);
486         }
487         /*------ DEBUG LOG END ------*/
488
489         /* check null */
490         if (srv == NULL) {
491                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,253, "Arg(srv) is NULL pointer.");
492                 return_value = -1;
493                 goto select_dest_out;
494         }
495         if (srv->pm == NULL) {
496                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,254, "Arg(srv->pm) is NULL pointer.");
497                 return_value = -1;
498                 goto select_dest_out;
499         }
500         if (request == NULL) {
501                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,255, "Arg(request) is NULL pointer.");
502                 return_value = -1;
503                 goto select_dest_out;
504         }
505         if (len == NULL) {
506                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,256, "Arg(len) is NULL pointer.");
507                 return_value = -1;
508                 goto select_dest_out;
509         }
510         if (dest == NULL) {
511                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,257, "Arg(dest) is NULL pointer.");
512                 return_value = -1;
513                 goto select_dest_out;
514         }
515
516         /* search service that has such a service ID */
517         pfilter_service = l7vs_protomod_pfilter_search_service(srv->handle);
518
519         /*-------- DEBUG LOG --------*/
520         if (pfilter_protomod.get_log_level != NULL &&
521             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
522                 char pfilter_str[DEBUG_STR_LEN] = {0};
523                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_service);
524                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,297, "pointer assign: pfilter_service=&(%s)",
525                     pfilter_str);
526         }
527         /*------ DEBUG LOG END ------*/
528
529         if (pfilter_service == NULL) {
530                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,259, "Could not find such service handle's pfilter service.");
531                 return_value = -1;
532                 goto select_dest_out;
533         }
534
535         /* initialize protocol module ... clear destination list */
536         ret = srv->pm->initialize(srv, conn, request, *len, dest);
537         if (ret != 0) {
538                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,260, "Could not initialize protomod.");
539                 return_value = -1;
540                 goto select_dest_out;
541         }
542
543         /* finalize */
544         ret = srv->pm->finalize(srv, conn, request, *len, dest, pfilter_service->reschedule);
545         if (ret != 0) {
546                 PUT_LOG_INFO(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,18, "Could not finalize protomod. (Realserver decision failure)");
547                 return_value = -1;
548                 goto select_dest_out;
549         }
550
551 select_dest_out:
552         /*-------- DEBUG LOG --------*/
553         if (pfilter_protomod.get_log_level != NULL &&
554             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
555                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,298,
556                     "out_function: int select_dest(struct l7vs_service* srv, struct l7vs_conn* conn, "
557                     "char* request, size_t* len, struct l7vs_dest** dest):return_value=%d",
558                     return_value);
559         }
560         /*------ DEBUG LOG END ------*/
561
562         return return_value;
563 }
564
565 /*!
566  * Check the client packet
567  * @param[in]  srv service struct include service handle, protocol module and schedule module.
568  * @param[in]  conn connection data.
569  * @param[in]  request packet data from client
570  * @param[in]  len length of packet data
571  * @retval 0  successfully check packet data
572  * @retval -1 some errors occur.
573  */
574 static int
575 analyze_cldata(struct l7vs_service *srv, struct l7vs_conn *conn,
576       char *request, size_t *len)
577 {
578         struct l7vs_pfilter_service *pfilter_service;
579         int ret;
580         int return_value = 0;
581     std::string packet_data;
582
583         /*-------- DEBUG LOG --------*/
584         if (pfilter_protomod.get_log_level != NULL &&
585             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
586                 char srv_str[DEBUG_STR_LEN] = {0};
587                 char conn_str[DEBUG_STR_LEN] = {0};
588                 char len_str[DEBUG_STR_LEN] = {0};
589                 l7vs_service_c_str(srv_str, srv);
590                 l7vs_conn_c_str(conn_str, conn);
591                 if (len != NULL) {
592                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
593                 }
594                 else {
595                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
596                 }
597                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,296,
598                     "in_function: int analyze_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
599                     "char* request, size_t* len):srv=&(%s), conn=&(%s), "
600                     "request=\"%s\", len=&(%s))",
601                     srv_str, conn_str, request, len_str);
602         }
603         /*------ DEBUG LOG END ------*/
604
605         /* check null */
606         if (srv == NULL) {
607                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,253, "Arg(srv) is NULL pointer.");
608                 return_value = -1;
609                 goto analyze_cldata_out;
610         }
611         if (srv->pm == NULL) {
612                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,254, "Arg(srv->pm) is NULL pointer.");
613                 return_value = -1;
614                 goto analyze_cldata_out;
615         }
616         if (request == NULL) {
617                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,255, "Arg(request) is NULL pointer.");
618                 return_value = -1;
619                 goto analyze_cldata_out;
620         }
621         if (len == NULL) {
622                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,256, "Arg(len) is NULL pointer.");
623                 return_value = -1;
624                 goto analyze_cldata_out;
625         }
626
627         /* search service that has such a service ID */
628         pfilter_service = l7vs_protomod_pfilter_search_service(srv->handle);
629
630         /*-------- DEBUG LOG --------*/
631         if (pfilter_protomod.get_log_level != NULL &&
632             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
633                 char pfilter_str[DEBUG_STR_LEN] = {0};
634                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_service);
635                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,297, "pointer assign: pfilter_service=&(%s)",
636                     pfilter_str);
637         }
638         /*------ DEBUG LOG END ------*/
639
640         if (pfilter_service == NULL) {
641                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,259, "Could not find such service handle's pfilter service.");
642                 return_value = -1;
643                 goto analyze_cldata_out;
644         }
645
646         /* check pattern_match != 0 */
647         if (pfilter_service->pattern_match[0] == '\0') {
648                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,261, "Pattern match is NULL pointer");
649                 return_value = -1;
650                 goto analyze_cldata_out;
651         }
652
653         /* check pattern match */
654         if (*len > pfilter_service->read_byte) {
655         packet_data = std::string(request, pfilter_service->read_byte);
656         }
657     else {
658         packet_data = std::string(request, *len);
659     }
660
661 #ifdef USE_BOOST_XPRESSIVE
662         if ( boost::xpressive::regex_search(packet_data, pfilter_service->regex) ) {
663 #else
664         if ( boost::regex_search(packet_data, pfilter_service->regex) ) {
665 #endif
666                 return_value = -1;
667                 goto analyze_cldata_out;
668         }
669
670 analyze_cldata_out:
671         /*-------- DEBUG LOG --------*/
672         if (pfilter_protomod.get_log_level != NULL &&
673             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
674                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,298,
675                     "out_function: int analyze_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
676                     "char* request, size_t* len):return_value=%d",
677                     return_value);
678         }
679         /*------ DEBUG LOG END ------*/
680
681         return return_value;
682 }
683
684 /*!
685  * Do nothing
686  * @param[in] srv service struct include service handle, protocol module and schedule module.
687  * @param[in] conn connection data.
688  * @param[in] response packet data from real server
689  * @param[in] len length of packet data. it will be lengthened.
690  * @retval 0  successfully check packet data.
691  * @retval -1 some errors occur.
692  */
693 static int
694 analyze_rsdata(struct l7vs_service *srv, struct l7vs_conn *conn,
695         char *response, size_t *len)
696 {
697         int return_value = 0;
698
699         /*-------- DEBUG LOG --------*/
700         if (pfilter_protomod.get_log_level != NULL &&
701             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
702                 char srv_str[DEBUG_STR_LEN] = {0};
703                 char conn_str[DEBUG_STR_LEN] = {0};
704                 char len_str[DEBUG_STR_LEN] = {0};
705                 l7vs_service_c_str(srv_str, srv);
706                 l7vs_conn_c_str(conn_str, conn);
707                 if (len != NULL) {
708                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
709                 }
710                 else {
711                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
712                 }
713                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,299,
714                     "in_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
715                     "char* response, size_t* len):srv=&(%s), conn=&(%s), response=\"%s\", len=&(%s)",
716                     srv_str, conn_str, response, len_str);
717         }
718         /*------ DEBUG LOG END ------*/
719
720         /* check null */
721         if (srv == NULL) {
722                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,262, "Arg(srv) is NULL pointer.");
723                 return_value = -1;
724                 goto analyze_rsdata_out;
725         }
726         if (conn == NULL) {
727                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,263, "Arg(conn) is NULL pointer.");
728                 return_value = -1;
729                 goto analyze_rsdata_out;
730         }
731         if (conn->dest == NULL) {
732                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,264, "Arg(conn->dest) is NULL pointer.");
733                 return_value = -1;
734                 goto analyze_rsdata_out;
735         }
736         if (response == NULL) {
737                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,265, "Arg(response) is NULL pointer.");
738                 return_value = -1;
739                 goto analyze_rsdata_out;
740         }
741         if (len == NULL) {
742                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,266, "Arg(len) is NULL pointer.");
743                 return_value = -1;
744                 goto analyze_rsdata_out;
745         }
746
747         /* sorry flag check */
748         if (conn->sorry_conn_flag == 1) {
749                 /*-------- DEBUG LOG --------*/
750                 if (pfilter_protomod.get_log_level != NULL &&
751                     LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
752                         PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,300, "Response from sorry server.");
753                 }
754                 /*------ DEBUG LOG END ------*/
755                 goto analyze_rsdata_out;
756         }
757
758 analyze_rsdata_out:
759         /*-------- DEBUG LOG --------*/
760         if (pfilter_protomod.get_log_level != NULL &&
761             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
762                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,301,
763                     "out_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
764                     "char* response, size_t* len):return_value=%d", return_value);
765         }
766         /*------ DEBUG LOG END ------*/
767
768         return return_value;
769 }
770
771 /*!
772  * Destroy pfilter service
773  * @param[in] srv_handle a unique service ID
774  * @retval 0  successfully check packet data.
775  * @retval -1 some errors occur.
776  */
777 static int
778 destroy(handle_t srv_handle)
779 {
780         /* pfilter service list counter */
781         int service_number = 0;
782         int free_flag = 0;
783         int return_value = 0;
784
785         /*-------- DEBUG LOG --------*/
786         if (pfilter_protomod.get_log_level != NULL &&
787             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
788                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,302,
789                     "in_function: int destroy(handle_t srv_handle):srv_handle=%u",
790                     srv_handle);
791         }
792         /*------ DEBUG LOG END ------*/
793
794         /* check all pfilter service list */
795         for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
796                 /* found pfilter service that has srv_handle */
797                 if (pfilter_service_list[service_number] != NULL && 
798                     pfilter_service_list[service_number]->service_handle == srv_handle) {
799
800                         /*-------- DEBUG LOG --------*/
801                         if (pfilter_protomod.get_log_level != NULL &&
802                             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
803                                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,65, "free: %p",
804                                     pfilter_service_list[service_number]);
805                         }
806                         /*------ DEBUG LOG END ------*/
807
808                         /* free and NULL */
809                         free(pfilter_service_list[service_number]);
810                         pfilter_service_list[service_number] = NULL;
811
812                         free_flag = 1;
813                         break;
814                 }
815         }
816         
817         /* pfilter service was not found */
818         if (free_flag == 0) {
819                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,267, "Could not find such service handle's pfilter service.");
820                 return_value = -1;
821                 goto destroy_out;
822         }
823
824 destroy_out:
825         /*-------- DEBUG LOG --------*/
826         if (pfilter_protomod.get_log_level != NULL &&
827             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
828                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,303,
829                     "out_function: int destroy(handle_t srv_handle):return_value=%d",
830                     srv_handle);
831         }
832         /*------ DEBUG LOG END ------*/
833
834         return return_value;
835 }
836
837 /*!
838  * Destroy pfilter service argument
839  * @param[in] pfilter_arg pfilter service argument
840  * @return void
841  */
842 static void
843 destroy_sa(void **pfilter_arg)
844 {
845         /*-------- DEBUG LOG --------*/
846         if (pfilter_protomod.get_log_level != NULL &&
847             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
848                 char pfilter_arg_str[DEBUG_STR_LEN] = {0};
849                 if (pfilter_arg != NULL) {
850                         l7vs_pfilter_service_arg_c_str(pfilter_arg_str, (struct l7vs_pfilter_service_arg*) *pfilter_arg);
851                 }
852                 else {
853                         strncpy(pfilter_arg_str, "NULL", DEBUG_STR_LEN);
854                 }
855                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,304,
856                     "in_function: void destroy_sa(void** pfilter_arg):pfilter_arg=&(&(%s))",
857                     pfilter_arg_str);
858         }
859         /*------ DEBUG LOG END ------*/
860
861         /* check null */
862         if (pfilter_arg == NULL) {
863                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,268, "Arg(pfilter_arg) is NULL pointer.");
864         }
865         else if (*pfilter_arg == NULL) {
866                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,269, "Arg(*pfilter_arg) is NULL pointer.");
867         }
868         else {
869                 /*-------- DEBUG LOG --------*/
870                 if (pfilter_protomod.get_log_level != NULL &&
871                     LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
872                         PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,66, "free: %p",
873                             *pfilter_arg);
874                 }
875                 /*------ DEBUG LOG END ------*/
876
877                 /* free and NULL */
878                 free((struct l7vs_pfilter_service_arg*) *pfilter_arg);
879                 *pfilter_arg = NULL;
880         }
881
882         /*-------- DEBUG LOG --------*/
883         if (pfilter_protomod.get_log_level != NULL &&
884             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
885                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,305,
886                     "out_function: void destroy_sa(void** pfilter_arg)");
887         }
888         /*------ DEBUG LOG END ------*/
889 }
890
891 /*!
892  * Create strings for service list of l7vsadm
893  * @param  srv_arg service argument struct
894  * @param  srv_handle a unique service ID
895  * @retval 0  successfully create strings
896  * @retval -1 some errors occur.
897  */
898 static int
899 service_arg(struct l7vs_service_arg_multi *srv_arg_mt, handle_t srv_handle)
900 {
901         struct l7vs_pfilter_service *pfilter_service;
902         struct l7vs_pfilter_service_arg c_sarg;
903         char pfilter_argument[SERVICE_ARG_MAXSIZE];
904         int return_value = 0;
905
906         /*-------- DEBUG LOG --------*/
907         if (pfilter_protomod.get_log_level != NULL &&
908             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
909                 char srv_arg_mt_str[DEBUG_STR_LEN] = {0};
910                 l7vs_service_arg_multi_c_str(srv_arg_mt_str, srv_arg_mt);
911                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,306,
912                     "in_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
913                     "handle_t srv_handle):srv_arg_mt=&(%s), srv_handle=%u",
914                     srv_arg_mt_str, srv_handle);
915         }
916         /*------ DEBUG LOG END ------*/
917
918         /* check null */
919         if (srv_arg_mt == NULL) {
920                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,270, "Arg(srv_arg_mt) is NULL pointer.");
921                 return_value = -1;
922                 goto service_arg_out;
923         }
924
925         /* search service that has such a service ID */
926         pfilter_service = l7vs_protomod_pfilter_search_service(srv_handle);
927
928         /*-------- DEBUG LOG --------*/
929         if (pfilter_protomod.get_log_level != NULL &&
930             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
931                 char pfilter_str[DEBUG_STR_LEN] = {0};
932                 l7vs_pfilter_service_c_str(pfilter_str, pfilter_service);
933                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,307, "pointer assign: pfilter_service=&(%s)",
934                     pfilter_str);
935         }
936         /*------ DEBUG LOG END ------*/
937
938         if (pfilter_service == NULL) {
939                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,271, "Could not find such service handle's pfilter service.");
940                 return_value = -1;
941                 goto service_arg_out;
942         }
943
944         /* initialize argument strings */
945         memset(pfilter_argument, 0, SERVICE_ARG_MAXSIZE);
946
947         /* set pfilter args to service argument struct */
948         srv_arg_mt->srv_arg.reschedule = pfilter_service->reschedule;
949
950
951         /* create long argument (l7vsadm option -L/-l) */
952         snprintf(pfilter_argument, SERVICE_ARG_MAXSIZE, "--pattern-match %s", pfilter_service->pattern_match);
953         strncpy(srv_arg_mt->srv_arg.protomod_key_string, pfilter_argument, 256);
954
955         /* create verbose argument (l7vsadm option -V/-v) */
956         snprintf(pfilter_argument, SERVICE_ARG_MAXSIZE, "--pattern-match %s --read-byte %d", pfilter_service->pattern_match, pfilter_service->read_byte);
957         strncpy(srv_arg_mt->srv_arg.protomod_opt_string, pfilter_argument, 512);
958
959         strncpy(c_sarg.pattern_match, pfilter_service->pattern_match, PATTERN_MATCH_MAXSIZE);
960         c_sarg.reschedule = pfilter_service->reschedule;
961
962         memcpy(srv_arg_mt->protomod_arg, &c_sarg, sizeof(struct l7vs_pfilter_service_arg));
963
964         /*-------- DEBUG LOG --------*/
965         if (pfilter_protomod.get_log_level != NULL &&
966             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
967                 char pfilter_arg_str[DEBUG_STR_LEN] = {0};
968                 l7vs_pfilter_service_arg_c_str(pfilter_arg_str, &c_sarg);
969                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,308,
970                     "pointer assign: srv_arg_mt->protomod_arg=&(%s)", pfilter_arg_str);
971         }
972         /*------ DEBUG LOG END ------*/
973
974 service_arg_out:
975         /*-------- DEBUG LOG --------*/
976         if (pfilter_protomod.get_log_level != NULL &&
977             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
978                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,309,
979                     "out_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
980                     "handle_t srv_handle):return_value=%d", return_value);
981         }
982         /*------ DEBUG LOG END ------*/
983
984         return return_value;
985 }
986
987 /*!
988  * Parse l7vsadm options to pfilter argument
989  * @param[out] pfilter_arg pfilter service argument struct
990  * @param[int] argc number of l7vsadm argument
991  * @param[int] argv l7vsadm argument list
992  * @retval 0  successfully parse argument
993  * @retval -1 some errors occur.
994  */
995 static int
996 parse(void *pfilter_arg, int argc, char *argv[])
997 {
998         struct l7vs_pfilter_service_arg *pfilter_service_arg;
999         static struct option opt[] = {
1000                 {"pattern-match",   required_argument, NULL, 'P'},
1001                 {"read-byte",       required_argument, NULL, 'R'},
1002                 {NULL,              0,                 NULL, 0  }
1003         };
1004         int c;
1005         unsigned long buffer;
1006         int pattern_match_flag = 0;
1007         int read_byte_flag = 0;
1008         int return_value = 0;
1009 #ifndef USE_BOOST_XPRESSIVE
1010         boost::regex regex;
1011 #endif
1012
1013         /*-------- DEBUG LOG --------*/
1014         if (pfilter_protomod.get_log_level != NULL &&
1015             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1016                 int i;
1017                 char argv_str[DEBUG_STR_LEN] = {0};
1018                 char pfilter_arg_str[DEBUG_STR_LEN] = {0};
1019                 l7vs_pfilter_service_arg_c_str(pfilter_arg_str, (struct l7vs_pfilter_service_arg*) pfilter_arg);
1020                 argv_str[0] = '\0';
1021                 if (argv == NULL)
1022                         snprintf(argv_str, DEBUG_STR_LEN, "NULL");
1023                 else {
1024                         for (i = 0; i < argc; i++) {
1025                                 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1026                         }
1027                         i = strnlen(argv_str, DEBUG_STR_LEN);
1028                         if (i > 1)
1029                                 argv_str[i - 2] = '\0';
1030                 }
1031                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,310,
1032                     "in_function: int parse(void* pfilter_arg, int argc, char* argv[]):pfilter_arg=&(%s), "
1033                     "argc=%d, %s", pfilter_arg_str, argc, argv_str);
1034         }
1035         /*------ DEBUG LOG END ------*/
1036
1037         /* check null */
1038         if (pfilter_arg == NULL) {
1039                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,272, "Arg(pfilter_arg) is NULL pointer.");
1040                 return_value = -1;
1041                 goto parse_out;
1042         }
1043         if (argv == NULL) {
1044                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,273, "Arg(argv) is NULL pointer.");
1045                 return_value = -1;
1046                 goto parse_out;
1047         }
1048
1049         pfilter_service_arg = (struct l7vs_pfilter_service_arg *) pfilter_arg;
1050         optind = 0;
1051
1052         /* check all argument */
1053         while ((c = getopt_long(argc, argv, "P:F", opt, NULL)) != -1) {
1054                 switch (c) {
1055                 /* --pattern-match / -P */
1056                 case 'P':
1057                         /* check maximum length */
1058                         if (strnlen(optarg, PATTERN_MATCH_MAXSIZE) >= PATTERN_MATCH_MAXSIZE) {
1059                                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,274,
1060                                     "-P/--pattern-match option value '%s' too long", optarg);
1061                                 return_value = -1;
1062                                 goto parse_out;
1063                         }
1064                         /* check minimum length */
1065                         if (strnlen(optarg, PATTERN_MATCH_MAXSIZE) <= 0 ) {
1066                                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,275,
1067                                     "-P/--pattern-match option value '%s' invalid", optarg);
1068                                 return_value = -1;
1069                                 goto parse_out;
1070                         }
1071                         strncpy(pfilter_service_arg->pattern_match, optarg, PATTERN_MATCH_MAXSIZE);
1072                         pattern_match_flag++;
1073                         break;
1074
1075                 /* --read_byte / -R */
1076                 case 'R':
1077                         if (sscanf(optarg, "%lu", &buffer) == 0) {
1078                                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,276,
1079                                     "-R/--read-byte option value '%s' is invalid.", optarg);
1080                                 return_value = -1;
1081                                 goto parse_out;
1082                         }
1083                         if (buffer > INT32_MAX) {
1084                                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,277,
1085                                     "-R/--read-byte option value '%s' is too large.", optarg);
1086                                 return_value = -1;
1087                                 goto parse_out;
1088                         }
1089                         else
1090                                 pfilter_service_arg->read_byte = buffer;
1091                         read_byte_flag++;
1092                         break;
1093
1094                 /* else error */
1095                 default:
1096                         PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,278, "Option error.");
1097                         return_value = -1;
1098                         goto parse_out;
1099                 }
1100         }
1101
1102         /* set default read byte */
1103         if (read_byte_flag == 0) {
1104                 pfilter_service_arg->read_byte = 1024;
1105         }
1106
1107         /* set default no reschedule */
1108         pfilter_service_arg->reschedule = 0;
1109
1110         /* no pattern-match value */
1111         if (pattern_match_flag == 0) {
1112                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,279,
1113                     "You have to set '--pattern-match' option.");
1114                 return_value = -1;
1115                 goto parse_out;
1116         }
1117         /* same option */
1118         if (pattern_match_flag > 1) {
1119                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,280,
1120                     "Cannot set multiple option '--pattern-match/-P'.");
1121                 return_value = -1;
1122                 goto parse_out;
1123         }
1124         /* compile regex */
1125     try {
1126 #ifdef USE_BOOST_XPRESSIVE
1127         boost::xpressive::sregex::compile(pfilter_service_arg->pattern_match);
1128 #else
1129         regex.assign(pfilter_service_arg->pattern_match);
1130 #endif
1131     }
1132     catch (...) {
1133                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,281,
1134                     "Regex pattern error.");
1135                 return_value = -1;
1136                 goto parse_out;
1137     }
1138
1139 parse_out:
1140         /*-------- DEBUG LOG --------*/
1141         if (pfilter_protomod.get_log_level != NULL &&
1142             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1143                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,311,
1144                     "out_function: int parse(void* pfilter_arg, int argc, char* argv[]):return_value=%d",
1145                     return_value);
1146         }
1147         /*------ DEBUG LOG END ------*/
1148
1149         return return_value;
1150 }
1151
1152 /*!
1153  * Search pfilter service from pfilter service list using service handle
1154  * @param[in]  service_handle a unique service ID
1155  * @return pfilter service struct when service was found. NULL when service was not found.
1156  */
1157 static struct l7vs_pfilter_service *
1158 l7vs_protomod_pfilter_search_service(handle_t service_handle)
1159 {
1160         /* pfilter service list counter */
1161         int service_number = 0;
1162         struct l7vs_pfilter_service* return_value = NULL;
1163
1164         /*-------- DEBUG LOG --------*/
1165         if (pfilter_protomod.get_log_level != NULL &&
1166             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1167                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,312,
1168                     "in_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_search_service(handle_t service_handle):"
1169                     "service_handle=%d", service_handle);
1170         }
1171         /*------ DEBUG LOG END ------*/
1172
1173         /* check all pfilter service list */
1174         for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
1175                 /* found the service has same service handle */
1176                 if (pfilter_service_list[service_number] != NULL && 
1177                     pfilter_service_list[service_number]->service_handle == service_handle) {
1178                         return_value = pfilter_service_list[service_number];
1179                         break;
1180                 }
1181         }
1182         
1183         /*-------- DEBUG LOG --------*/
1184         if (pfilter_protomod.get_log_level != NULL &&
1185             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1186                 char ssl_str[DEBUG_STR_LEN] = {0};
1187                 l7vs_pfilter_service_c_str(ssl_str, return_value);
1188                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,313,
1189                     "out_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_search_service(handle_t service_handle):"
1190                     "return_value=&(%s)", ssl_str);
1191         }
1192         /*------ DEBUG LOG END ------*/
1193
1194         return return_value;
1195 }
1196
1197 /*!
1198  * Create pfilter service.
1199  * @param  void
1200  * @return pfilter service struct when create a service. NULL when cannot create service.
1201  */
1202 static struct l7vs_pfilter_service *
1203 l7vs_protomod_pfilter_create_service()
1204 {
1205         struct l7vs_pfilter_service* return_value = NULL;
1206         int service_number = 0;
1207
1208         /*-------- DEBUG LOG --------*/
1209         if (pfilter_protomod.get_log_level != NULL &&
1210             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1211                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,314,
1212                     "in_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_create_service()");
1213         }
1214         /*------ DEBUG LOG END ------*/
1215
1216         /* check all pfilter service list */
1217         for (service_number = 0; service_number < URL_SERVICE_NUMBER - 1; ++service_number) {
1218                 /* if pointer that does not point NULL exists ... */
1219                 if (pfilter_service_list[service_number] == NULL) {
1220                         /* create a service at empty pointer */
1221                         pfilter_service_list[service_number] = (struct l7vs_pfilter_service *) calloc(1, sizeof(struct l7vs_pfilter_service));
1222
1223                         /*-------- DEBUG LOG --------*/
1224                         if (pfilter_protomod.get_log_level != NULL &&
1225                             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1226                                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,67, "calloc: addr=%p, size=%ld",
1227                                     pfilter_service_list[service_number], (unsigned long int) sizeof(struct l7vs_pfilter_service));
1228                         }
1229                         /*------ DEBUG LOG END ------*/
1230
1231                         if (pfilter_service_list[service_number] == NULL) {
1232                                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,57, "Could not allocate memory.");
1233                                 goto create_service_out;
1234                         }
1235                         return_value = pfilter_service_list[service_number];
1236                         goto create_service_out;
1237                 }
1238         }
1239         
1240         /* all service list is full */
1241         PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,282, "pfilter service list is full.");
1242
1243 create_service_out:
1244         /*-------- DEBUG LOG --------*/
1245         if (pfilter_protomod.get_log_level != NULL &&
1246             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1247                 char ssl_str[DEBUG_STR_LEN] = {0};
1248                 l7vs_pfilter_service_c_str(ssl_str, return_value);
1249                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,315,
1250                     "out_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_create_service():"
1251                     "return_value=&(%s)", ssl_str);
1252         }
1253         /*------ DEBUG LOG END ------*/
1254
1255         return return_value;
1256 }
1257
1258 /*!
1259  * Create temporary pfilter service.
1260  * @param  void
1261  * @return pfilter service struct when create a service. NULL when cannot create service.
1262  */
1263 static struct l7vs_pfilter_service *
1264 l7vs_protomod_pfilter_create_temp_service()
1265 {
1266         struct l7vs_pfilter_service* return_value = NULL;
1267
1268         /*-------- DEBUG LOG --------*/
1269         if (pfilter_protomod.get_log_level != NULL &&
1270             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1271                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,316,
1272                     "in_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_create_temp_service()");
1273         }
1274         /*------ DEBUG LOG END ------*/
1275
1276         /* if pointer that does not point NULL exists ... */
1277         if (pfilter_service_list[URL_SERVICE_NUMBER - 1] != NULL) {
1278                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,283, "Temporary pfilter service is being used by other process.");
1279                 goto create_temp_service_out;
1280         }
1281
1282         /* create temp service */
1283         pfilter_service_list[URL_SERVICE_NUMBER - 1] = (struct l7vs_pfilter_service *) calloc(1, sizeof(struct l7vs_pfilter_service));
1284
1285         /*-------- DEBUG LOG --------*/
1286         if (pfilter_protomod.get_log_level != NULL &&
1287             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1288                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,68, "calloc: addr=%p, size=%ld",
1289                     pfilter_service_list[URL_SERVICE_NUMBER - 1], (unsigned long int) sizeof(struct l7vs_pfilter_service));
1290         }
1291         /*------ DEBUG LOG END ------*/
1292
1293         if (pfilter_service_list[URL_SERVICE_NUMBER - 1] == NULL) {
1294                 PUT_LOG_ERROR(pfilter_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,58, "Could not allocate memory");
1295                 goto create_temp_service_out;
1296         }
1297
1298         return_value = pfilter_service_list[URL_SERVICE_NUMBER - 1];
1299
1300 create_temp_service_out:
1301         /*-------- DEBUG LOG --------*/
1302         if (pfilter_protomod.get_log_level != NULL &&
1303             LOG_LV_DEBUG == pfilter_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1304                 char ssl_str[DEBUG_STR_LEN] = {0};
1305                 l7vs_pfilter_service_c_str(ssl_str, return_value);
1306                 PUT_LOG_DEBUG(pfilter_protomod, LOG_CAT_L7VSD_PROTOCOL,317,
1307                     "out_function: struct l7vs_pfilter_service* l7vs_protomod_pfilter_create_service():"
1308                     "return_value=&(%s)", ssl_str);
1309         }
1310         /*------ DEBUG LOG END ------*/
1311
1312         return return_value;
1313 }
1314
1315 /*!
1316  * Serialize struct l7vs_pfilter_service for debug log.
1317  * @param[out] buf   serialized string
1318  * @param[in]  pfilter l7vs_pfilter_service struct
1319  */
1320 static void l7vs_pfilter_service_c_str(char* buf, struct l7vs_pfilter_service* pfilter) {
1321         if (pfilter == NULL) {
1322                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1323         }
1324         else {
1325                 snprintf(buf, DEBUG_STR_LEN, "service_handle=%d, pattern_match=\"%s\", "
1326                     "read_byte=%d, reschedule=%d", pfilter->service_handle, pfilter->pattern_match,
1327                     pfilter->read_byte, pfilter->reschedule);
1328         }
1329 }
1330
1331 /*!
1332  * Serialize struct l7vs_pfilter_service_arg for debug log.
1333  * @param[out] buf       serialized string
1334  * @param[in]  pfilter_arg l7vs_pfilter_service_arg struct
1335  */
1336 void l7vs_pfilter_service_arg_c_str(char* buf, struct l7vs_pfilter_service_arg* pfilter_arg) {
1337         if (pfilter_arg == NULL) {
1338                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1339         }
1340         else {
1341                 snprintf(buf, DEBUG_STR_LEN, "pattern_match=\"%s\", read_byte=%d, reschedule=%d",
1342                     pfilter_arg->pattern_match, pfilter_arg->read_byte, pfilter_arg->reschedule);
1343         }
1344 }