OSDN Git Service

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