OSDN Git Service

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