OSDN Git Service

Merge commit 'origin/sslid-fix' into 2.1.2-2-rc
[ultramonkey-l7/ultramonkey-l7-v2.git] / module / protocol / protomod_sslid.c
1 /*
2  * @file  protomod_sslid.c
3  * @brief protocol module of HTTPS(SSL/TLS).
4  * @brief this module provide session persistence by SSL session ID.
5  *
6  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7  * Copyright (C) 2008  NTT COMWARE Corporation.
8  * Copyright (C) 2009  Shinya TAKEBAYASHI
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License as published by the Free Software Foundation; either
13  * version 2.1 of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with this library; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
23  * 02110-1301 USA
24  *
25  **********************************************************************/
26
27 #define __STDC_LIMIT_MACROS
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <time.h>
33 #include <getopt.h>
34 #include "l7vs_service.h"
35 #include "l7vs_conn.h"
36 #include "l7vs_lsock.h"
37 #include "l7vs_dest.h"
38 #include "l7vs_replication.h"
39 #include "l7vs_module.h"
40 #include "module_http.h"
41 #include "module_sslid_hash.h"
42 #include "protomod_sslid.h"
43
44 static void  fini(void);
45 static int   create(void*, handle_t);
46 static void* create_sa(struct l7vs_service_arg*);
47 static int   compare(handle_t, handle_t);
48 static int   match_cldata(struct l7vs_service*, struct l7vs_conn*,
49                         char*, size_t*, struct l7vs_dest**, int*);
50 static int   analyze_rsdata(struct l7vs_service*, struct l7vs_conn*,
51                         char*, size_t*);
52 static int   destroy(handle_t);
53 static void  destroy_sa(void**);
54 static int   service_arg(struct l7vs_service_arg_multi*, handle_t);
55 static int   parse(void*, int, char**);
56
57 static struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t);
58 static struct l7vs_sslid_service* l7vs_protomod_sslid_create_service();
59 static struct l7vs_sslid_service* l7vs_protomod_sslid_create_temp_service();
60
61 static void l7vs_protomod_sslid_read_replication_data(struct l7vs_sslid_service*, struct l7vs_service*);
62 static void l7vs_protomod_sslid_write_replication_data(struct l7vs_sslid_service*);
63
64 static void l7vs_sslid_service_c_str(char*, struct l7vs_sslid_service*);
65 static void l7vs_sslid_service_arg_c_str(char*, struct l7vs_sslid_service_arg*);
66 static void ssl_session_c_str(char*, struct ssl_session*);
67 static void replication_header_c_str(char*, struct replication_header*);
68 static void id_c_str(char*, char*);
69
70 struct l7vs_sslid_service* sslid_service_list[SSLID_SERVICE_NUMBER];
71
72 static struct l7vs_protomod sslid_protomod = {
73         NULL,           /* handle */
74         "sslid",        /* modname */
75         0,              /* refcnt */
76         0,              /* fast schedule */
77         create,         /* create function */
78         compare,        /* compare function */
79         match_cldata,   /* match_cldata function */
80         analyze_rsdata, /* analyze_rsdata function */
81         destroy,        /* destroy function */
82         fini,           /* fini function */
83         create_sa,      /* create_sa function */
84         service_arg,    /* service_arg function */
85         parse,          /* parse function */
86         destroy_sa,     /* destroy_sa function */
87         NULL,           /* initialize function */
88         NULL,           /* finalize function */
89         NULL,           /* get_log_level function */
90         NULL,           /* put_log_debug function */
91         NULL,           /* put_log_info function */
92         NULL,           /* put_log_warn function */
93         NULL,           /* put_log_error function */
94         NULL,           /* put_log_fatal function */
95         NULL            /* replication_pay_memory function */
96 };
97
98 /*!
99  * Protocol module initialize function. This function run when dlopen and dlsym at first time.
100  * @param[in] handle dlopen's handle
101  * @return l7vs_protomod struct
102  */
103 extern "C" struct l7vs_protomod*
104 init(void* handle)
105 {
106         struct l7vs_protomod* return_value = NULL;
107
108         /*-------- DEBUG LOG --------*/
109         if (sslid_protomod.get_log_level != NULL &&
110             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
111                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,92,
112                     "in_function: struct l7vs_protomod* init(void* handle): handle=%p", handle);
113         }
114         /*------ DEBUG LOG END ------*/
115
116         /* check null */
117         if (handle == NULL) {
118                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,79, "Arg(handle) is NULL pointer.");
119                 goto init_out;
120         }
121
122         /* initialize sslid service list */
123         memset(sslid_service_list, 0, sizeof(struct l7vs_sslid_service*) * SSLID_SERVICE_NUMBER);
124         /* set dlopen's handle */
125         sslid_protomod.handle = handle;
126
127         return_value = &sslid_protomod;
128
129 init_out:
130         /*-------- DEBUG LOG --------*/
131         if (sslid_protomod.get_log_level != NULL &&
132             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
133                 char protomod_str[DEBUG_STR_LEN] = {0};
134                 l7vs_protomod_c_str(protomod_str, &sslid_protomod);
135                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,93,
136                     "out_function: struct l7vs_protomod* init(void* handle): return=&(%s)", protomod_str);
137         }
138         /*------ DEBUG LOG END ------*/
139         return return_value;
140 }
141
142 /*!
143  * Protocol module finalize function. free all sslid service list just in case.
144  * @param   void
145  * @return  void
146  */
147 static void
148 fini(void)
149 {
150         /* sslid service list counter */
151         int service_number = 0;
152
153         /*-------- DEBUG LOG --------*/
154         if (sslid_protomod.get_log_level != NULL &&
155             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
156                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,94, "in_function: void fini(void)");
157         }
158         /*------ DEBUG LOG END ------*/
159
160         /* check all sslid service list */
161         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
162                 /* if pointer that does not point NULL exists ... */
163                 if (sslid_service_list[service_number] != NULL) {
164                         /* free and points NULL */
165                         if (sslid_service_list[service_number]->session != NULL) {
166
167                                 /*-------- DEBUG LOG --------*/
168                                 if (sslid_protomod.get_log_level != NULL &&
169                                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
170                                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,25, "free: %p",
171                                             sslid_service_list[service_number]->session);
172                                 }
173                                 /*------ DEBUG LOG END ------*/
174
175                                 free(sslid_service_list[service_number]->session);
176                                 sslid_service_list[service_number]->session = NULL;
177                                 hash_setPointer(sslid_service_list[service_number]->hash_map, sslid_service_list[service_number]->hash_list, sslid_service_list[service_number]->maxlist);
178                                 hash_destroy();
179                         }
180
181                         /*-------- DEBUG LOG --------*/
182                         if (sslid_protomod.get_log_level != NULL &&
183                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
184                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,26, "free: %p",
185                                     sslid_service_list[service_number]);
186                         }
187                         /*------ DEBUG LOG END ------*/
188
189                         free(sslid_service_list[service_number]);
190                         sslid_service_list[service_number] = NULL;
191                 }
192         }
193
194         /*-------- DEBUG LOG --------*/
195         if (sslid_protomod.get_log_level != NULL &&
196             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
197                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,95, "out_function: void fini(void)");
198         }
199         /*------ DEBUG LOG END ------*/
200 }
201
202 /*!
203  * Create sslid service struct.
204  * @param[in] sslid_arg      sslid service argument struct
205  * @param[in] service_handle a unique service ID
206  * @retval 0  successfully create sslid service.
207  * @retval -1 some errors occur.
208  */
209 static int
210 create(void* sslid_arg, handle_t service_handle)
211 {
212         struct l7vs_sslid_service* sslid_service;
213         struct l7vs_sslid_service_arg* sslid_service_arg;
214         int return_value = 0;
215
216         /*-------- DEBUG LOG --------*/
217         if (sslid_protomod.get_log_level != NULL &&
218             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
219                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
220                 l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) sslid_arg);
221                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,96,
222                     "in_function: int create(void* sslid_arg, handle_t service_handle):sslid_arg=&(%s), "
223                     "service_handle=%d", sslid_arg_str, service_handle);
224         }
225         /*------ DEBUG LOG END ------*/
226
227         /* check null */
228         if (sslid_arg == NULL) {
229                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,80, "Arg(sslid_arg) is NULL pointer.");
230                 return_value = -1;
231                 goto create_out;
232         }
233
234         if (service_handle != TEMP_SERVICEHANDLE) {
235                 /* search empty sslid service list and create sslid service */
236                 sslid_service = l7vs_protomod_sslid_create_service();
237         }
238         else {
239                 /* create temporary sslid service */
240                 sslid_service = l7vs_protomod_sslid_create_temp_service();
241         }
242
243         /*-------- DEBUG LOG --------*/
244         if (sslid_protomod.get_log_level != NULL &&
245             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
246                 char sslid_str[DEBUG_STR_LEN] = {0};
247                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
248                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,97, "pointer assign: sslid_service=&(%s)",
249                     sslid_str);
250         }
251         /*------ DEBUG LOG END ------*/
252
253         if (sslid_service == NULL) {
254                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,81, "Could not make sslid service.");
255                 return_value = -1;
256                 goto create_out;
257         }
258
259         sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
260
261         /* set service handle */
262         sslid_service->service_handle = service_handle;
263
264         /* set option value */
265         sslid_service->timeout = sslid_service_arg->timeout;
266         sslid_service->maxlist = sslid_service_arg->maxlist;
267         sslid_service->replication_addr = NULL;
268         sslid_service->reschedule = sslid_service_arg->reschedule;
269
270         if (service_handle != TEMP_SERVICEHANDLE) {
271                 /* create session area */
272                 sslid_service->session = (struct ssl_session*) calloc(sizeof(struct ssl_session), sslid_service->maxlist);
273                 hash_allocate(sslid_service_arg->maxlist);
274                 sslid_service->hash_map = hash_getIDMAP();
275                 sslid_service->hash_list = hash_getIDLIST();
276
277                 /*-------- DEBUG LOG --------*/
278                 if (sslid_protomod.get_log_level != NULL &&
279                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
280                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,27, "calloc: addr=%p, size=%ld",
281                             sslid_service->session, (unsigned long int) sizeof(struct ssl_session) * sslid_service->maxlist);
282                 }
283                 /*------ DEBUG LOG END ------*/
284
285                 if (sslid_service->session == NULL) {
286                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,22, "Could not allocate memory.");
287                         if (destroy(service_handle)) {
288                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,23,
289                                     "Could not destroy SSL service. (handle=%d)", service_handle);
290                         }
291                         return_value = -1;
292                         goto create_out;
293                 }
294         }
295
296 create_out:
297         /*-------- DEBUG LOG --------*/
298         if (sslid_protomod.get_log_level != NULL &&
299             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
300                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,98,
301                     "out_function: int create(void* sslid_arg, handle_t service_handle):return_value=%d",
302                     return_value);
303         }
304         /*------ DEBUG LOG END ------*/
305
306         return return_value;
307 }
308
309 /*!
310  * Create sslid service argument struct.
311  * @param[out] srv_arg service argument struct
312  * @return sslid service argument struct
313  */
314 static void*
315 create_sa(struct l7vs_service_arg* srv_arg)
316 {
317         struct l7vs_sslid_service_arg* sslid_service_arg;
318
319         /*-------- DEBUG LOG --------*/
320         if (sslid_protomod.get_log_level != NULL &&
321             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
322                 char service_arg_str[DEBUG_STR_LEN] = {0};
323                 l7vs_service_arg_c_str(service_arg_str, srv_arg);
324                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,99,
325                     "in_function: void* create_sa(struct l7vs_service_arg* srv_arg):srv_arg=&(%s)",
326                     service_arg_str);
327         }
328         /*------ DEBUG LOG END ------*/
329
330         /* check null */
331         if (srv_arg == NULL) {
332                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,82, "Arg(srv_arg) is NULL pointer.");
333                 sslid_service_arg = NULL;
334                 goto create_sa_out;
335         }
336
337         /* create sslid service argument struct */
338         sslid_service_arg = (struct l7vs_sslid_service_arg*) calloc(1, sizeof(struct l7vs_sslid_service_arg));
339
340         /*-------- DEBUG LOG --------*/
341         if (sslid_protomod.get_log_level != NULL &&
342             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
343                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,28, "calloc: addr=%p, size=%ld",
344                     sslid_service_arg, (unsigned long int) sizeof(struct l7vs_sslid_service_arg));
345         }
346         /*------ DEBUG LOG END ------*/
347
348         if (sslid_service_arg == NULL) {
349                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,24, "Could not allocate memory.");
350                 goto create_sa_out;
351         }
352
353         /* set sslid service argument size and protomod name "sslid" */
354         srv_arg->len = sizeof(struct l7vs_sslid_service_arg);
355         strcpy(srv_arg->protomod, sslid_protomod.modname);
356
357 create_sa_out:
358         /*-------- DEBUG LOG --------*/
359         if (sslid_protomod.get_log_level != NULL &&
360             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
361                 char sslid_service_arg_str[DEBUG_STR_LEN] = {0};
362                 l7vs_sslid_service_arg_c_str(sslid_service_arg_str, sslid_service_arg);
363                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,100,
364                     "out_function: void* create_sa(struct l7vs_service_arg* srv_arg):return_value=&(%s)",
365                     sslid_service_arg_str);
366         }
367         /*------ DEBUG LOG END ------*/
368
369         return (void*) sslid_service_arg;
370 }
371
372 /*!
373  * Always match 'cause SSL-Session-ID module does not have module key.
374  * @param[in] srv_handle1 one of a unique service ID
375  * @param[in] srv_handle2 one of a unique service ID
376  * @retval 0  they matched perfectly.
377  * @retval -1 they are different.
378  */
379 static int
380 compare(handle_t srv_handle1, handle_t srv_handle2)
381 {
382         int return_value = 0;
383
384         /*-------- DEBUG LOG --------*/
385         if (sslid_protomod.get_log_level != NULL &&
386             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
387                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,101,
388                     "in_function: int compare(handle_t srv_handle1, handle_t srv_handle2):"
389                     "srv_handle1=%u, srv_handle2=%u", srv_handle1, srv_handle2);
390         }
391         /*------ DEBUG LOG END ------*/
392
393         /*-------- DEBUG LOG --------*/
394         if (sslid_protomod.get_log_level != NULL &&
395             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
396                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,102,
397                     "out_function: int compare(handle_t srv_handle1, handle_t srv_handle2):return_value=%d",
398                     return_value);
399         }
400         /*------ DEBUG LOG END ------*/
401
402         return return_value;
403 }
404
405 /*!
406  * Check and modify request packet.
407  * @param[in]  srv     service struct include service handle, protocol module and schedule module.
408  * @param[in]  conn    connection data.
409  * @param[in]  request packet data from client
410  * @param[in]  len     length of packet data
411  * @param[out] dest    destination (real server) list
412  * @param[out] tcps    TCP Splicer flag
413  * @retval 0  successfully check packet data
414  * @retval -1 some errors occur.
415  */
416 static int
417 match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn,
418       char* request, size_t* len, struct l7vs_dest** dest, int* tcps)
419 {
420         struct l7vs_sslid_service* sslid_service;
421         int i;
422         int ret;
423         int return_value = 0;
424         time_t now;
425         char id_str[DEBUG_STR_LEN] = {0};
426         struct l7vs_dest *tmpdest = NULL;
427         int searchret = -1;
428
429         /*-------- DEBUG LOG --------*/
430         if (sslid_protomod.get_log_level != NULL &&
431             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
432                 char srv_str[DEBUG_STR_LEN] = {0};
433                 char conn_str[DEBUG_STR_LEN] = {0};
434                 char dest_str[DEBUG_STR_LEN] = {0};
435                 char len_str[DEBUG_STR_LEN] = {0};
436                 l7vs_service_c_str(srv_str, srv);
437                 l7vs_conn_c_str(conn_str, conn);
438                 if (dest != NULL) {
439                         l7vs_dest_c_str(dest_str, *dest);
440                 }
441                 else {
442                         strncpy(dest_str, "NULL", DEBUG_STR_LEN);
443                 }
444                 if (len != NULL) {
445                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
446                 }
447                 else {
448                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
449                 }
450                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,103,
451                     "in_function: int match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
452                     "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):srv=&(%s), conn=&(%s), "
453                     "request=\"%s\", len=&(%s), dest=&(&(%s)), tcps=&(%d)",
454                     srv_str, conn_str, request, len_str, dest_str, *tcps);
455         }
456         /*------ DEBUG LOG END ------*/
457
458         /* check null */
459         if (srv == NULL) {
460                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,83, "Arg(srv) is NULL pointer.");
461                 return_value = -1;
462                 goto match_cldata_out;
463         }
464         if (srv->pm == NULL) {
465                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,84, "Arg(srv->pm) is NULL pointer.");
466                 return_value = -1;
467                 goto match_cldata_out;
468         }
469         if (request == NULL) {
470                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,85, "Arg(request) is NULL pointer.");
471                 return_value = -1;
472                 goto match_cldata_out;
473         }
474         if (len == NULL) {
475                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,86, "Arg(len) is NULL pointer.");
476                 return_value = -1;
477                 goto match_cldata_out;
478         }
479         if (dest == NULL) {
480                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,87, "Arg(dest) is NULL pointer.");
481                 return_value = -1;
482                 goto match_cldata_out;
483         }
484         if (tcps == NULL) {
485                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,88, "Arg(tcps) is NULL pointer.");
486                 return_value = -1;
487                 goto match_cldata_out;
488         }
489
490         /* search service that has such a service ID */
491         sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
492
493         /*-------- DEBUG LOG --------*/
494         if (sslid_protomod.get_log_level != NULL &&
495             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
496                 char sslid_str[DEBUG_STR_LEN] = {0};
497                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
498                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,104, "pointer assign: sslid_service=&(%s)",
499                     sslid_str);
500         }
501         /*------ DEBUG LOG END ------*/
502
503         if (sslid_service == NULL) {
504                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,89, "Could not find such service handle's sslid service.");
505                 return_value = -1;
506                 goto match_cldata_out;
507         }
508         if (sslid_service->session == NULL) {
509                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,90,
510                     "Service has NULL pointer session.");
511                 return_value = -1;
512                 goto match_cldata_out;
513         }
514
515         /* read replication data */
516         if (sslid_service->replication_addr) {
517                 l7vs_protomod_sslid_read_replication_data(sslid_service, srv);
518                 hash_rebuild_sessionlist(sslid_service);
519         }
520
521         /* initialize protocol module ... clear destination list */
522         ret = srv->pm->initialize(srv, conn, request, *len, dest);
523         if (ret != 0){
524                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,91, "Could not initialize protomod.");
525                 return_value = -1;
526                 goto match_cldata_out;
527         }
528
529         /* check payload */
530         if (
531             *len > 75 &&
532             (
533              (request[1] == 0x03 && request[2] == 0x00 && request[9] == 0x03 && request [10] == 0x00) || // SSL v3
534              (request[1] == 0x03 && request[2] == 0x01 && request[9] == 0x03 && request [10] == 0x01)    // TLS v1
535             ) &&
536             request[5] == 0x01 && // Client Hello
537             request[43] == 0x20 // Session ID Length
538            ) {
539                 /*-------- DEBUG LOG --------*/
540                 if (sslid_protomod.get_log_level != NULL &&
541                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
542                         char id_str[DEBUG_STR_LEN] = {0};
543                         id_c_str(id_str, &request[44]);
544                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105,
545                             "Client Hello/SessionID=%s", id_str);
546                 }
547                 /*------ DEBUG LOG END ------*/
548
549                 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
550                 id_c_str(id_str, &request[44]);
551                 searchret = hash_search(id_str, &tmpdest);
552                 
553                 if (searchret == 0) {
554                         *dest = tmpdest;
555                 }
556                 
557         }
558
559         *tcps = 0;
560
561         /* finalize, always set reschedule flag */
562         ret = srv->pm->finalize(srv, conn, request, *len, dest, sslid_service->reschedule);
563         if (ret != 0){
564                 PUT_LOG_INFO(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,11, "Could not finalize protomod. (Realserver decision failure)");
565                 return_value = -1;
566                 goto match_cldata_out;
567         }
568
569 match_cldata_out:
570         /*-------- DEBUG LOG --------*/
571         if (sslid_protomod.get_log_level != NULL &&
572             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
573                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
574                     "out_function: int match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
575                     "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):return_value=%d",
576                     return_value);
577         }
578         /*------ DEBUG LOG END ------*/
579
580         return return_value;
581 }
582
583 /*!
584  * Check and modify response packet.
585  * @param[in] srv      service struct include service handle, protocol module and schedule module.
586  * @param[in] conn     connection data.
587  * @param[in] response packet data from real server
588  * @param[in] len      length of packet data. it will be lengthened.
589  * @retval 0  successfully check packet data.
590  * @retval -1 some errors occur.
591  */
592 static int
593 analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn,
594         char* response, size_t* len)
595 {
596         struct l7vs_sslid_service* sslid_service;
597         int exist = 0;
598         int return_value = 0;
599         int i;
600         int pick;
601         time_t now, oldest = 0;
602         char session_full = 1;
603         char id_str[DEBUG_STR_LEN] = {0};
604
605         /*-------- DEBUG LOG --------*/
606         if (sslid_protomod.get_log_level != NULL &&
607             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
608                 char srv_str[DEBUG_STR_LEN] = {0};
609                 char conn_str[DEBUG_STR_LEN] = {0};
610                 char len_str[DEBUG_STR_LEN] = {0};
611                 l7vs_service_c_str(srv_str, srv);
612                 l7vs_conn_c_str(conn_str, conn);
613                 if (len != NULL) {
614                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
615                 }
616                 else {
617                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
618                 }
619                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
620                     "in_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
621                     "char* response, size_t* len):srv=&(%s), conn=&(%s), response=\"%s\", len=&(%s)",
622                     srv_str, conn_str, response, len_str);
623         }
624         /*------ DEBUG LOG END ------*/
625
626         /* check null */
627         if (srv == NULL) {
628                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,93, "Arg(srv) is NULL pointer.");
629                 return_value = -1;
630                 goto analyze_rsdata_out;
631         }
632         if (conn == NULL) {
633                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,94, "Arg(conn) is NULL pointer.");
634                 return_value = -1;
635                 goto analyze_rsdata_out;
636         }
637         if (conn->dest == NULL) {
638                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,95, "Arg(conn->dest) is NULL pointer.");
639                 return_value = -1;
640                 goto analyze_rsdata_out;
641         }
642         if (response == NULL) {
643                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,96, "Arg(response) is NULL pointer.");
644                 return_value = -1;
645                 goto analyze_rsdata_out;
646         }
647         if (len == NULL) {
648                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,97, "Arg(len) is NULL pointer.");
649                 return_value = -1;
650                 goto analyze_rsdata_out;
651         }
652
653         /* sorry flag check */
654         if (conn->sorry_conn_flag == 1) {
655                 /*-------- DEBUG LOG --------*/
656                 if (sslid_protomod.get_log_level != NULL &&
657                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
658                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109, "Response from sorry server.");
659                 }
660                 /*------ DEBUG LOG END ------*/
661
662                 goto analyze_rsdata_out;
663         }
664
665         /* search service that has such a service ID */
666         sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
667
668         /*-------- DEBUG LOG --------*/
669         if (sslid_protomod.get_log_level != NULL &&
670             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
671                 char sslid_str[DEBUG_STR_LEN] = {0};
672                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
673                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110, "pointer assign: sslid_service=&(%s)",
674                     sslid_str);
675         }
676         /*------ DEBUG LOG END ------*/
677
678         if (sslid_service == NULL) {
679                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,98,
680                     "Could not find such service handle's sslid service.");
681                 return_value = -1;
682                 goto analyze_rsdata_out;
683         }
684         if (sslid_service->session == NULL) {
685                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,99,
686                     "Service has NULL pointer session.");
687                 return_value = -1;
688                 goto analyze_rsdata_out;
689         }
690
691         /* check payload */
692         if (
693             *len > 75 &&
694             (
695              (response[1] == 0x03 && response[2] == 0x00 && response[9] == 0x03 && response [10] == 0x00) || // SSL v3
696              (response[1] == 0x03 && response[2] == 0x01 && response[9] == 0x03 && response [10] == 0x01)    // TLS v1
697             ) &&
698             response[5]  == 0x02 && // Server Hello
699             response[43] == 0x20 // Session ID Length
700            ) {
701                 /*-------- DEBUG LOG --------*/
702                 if (sslid_protomod.get_log_level != NULL &&
703                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
704                         char id_str[DEBUG_STR_LEN] = {0};
705                         id_c_str(id_str, &response[44]);
706                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111,
707                             "Server Hello/SessionID=%s", id_str);
708                 }
709                 /*------ DEBUG LOG END ------*/
710
711                 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
712                 id_c_str(id_str, &response[44]);
713                 hash_add(id_str, *conn->dest);
714                 if (sslid_service->replication_addr) {
715                         hash_construct_sessionlist(sslid_service);
716                         l7vs_protomod_sslid_write_replication_data(sslid_service);
717                 }
718         }
719
720 analyze_rsdata_out:
721         /*-------- DEBUG LOG --------*/
722         if (sslid_protomod.get_log_level != NULL &&
723             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
724                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
725                     "out_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
726                     "char* response, size_t* len):return_value=%d", return_value);
727         }
728         /*------ DEBUG LOG END ------*/
729
730         return return_value;
731 }
732
733 /*!
734  * Destroy sslid service
735  * @param[in] srv_handle a unique service ID
736  * @retval 0  successfully check packet data.
737  * @retval -1 some errors occur.
738  */
739 static int
740 destroy(handle_t srv_handle)
741 {
742         /* sslid service list counter */
743         int service_number = 0;
744         int free_flag = 0;
745         int return_value = 0;
746
747         /*-------- DEBUG LOG --------*/
748         if (sslid_protomod.get_log_level != NULL &&
749             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
750                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115,
751                     "in_function: int destroy(handle_t srv_handle):srv_handle=%u",
752                     srv_handle);
753         }
754         /*------ DEBUG LOG END ------*/
755
756         /* check all sslid service list */
757         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
758                 /* found sslid service that has srv_handle */
759                 if (sslid_service_list[service_number] != NULL && 
760                     sslid_service_list[service_number]->service_handle == srv_handle) {
761
762                         /* free and NULL */
763                         if (sslid_service_list[service_number]->session != NULL) {
764
765                                 /*-------- DEBUG LOG --------*/
766                                 if (sslid_protomod.get_log_level != NULL &&
767                                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
768                                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,29, "free: %p",
769                                             sslid_service_list[service_number]->session);
770                                 }
771                                 /*------ DEBUG LOG END ------*/
772
773                                 free(sslid_service_list[service_number]->session);
774                                 sslid_service_list[service_number]->session = NULL;
775                                 hash_setPointer(sslid_service_list[service_number]->hash_map, sslid_service_list[service_number]->hash_list, sslid_service_list[service_number]->maxlist);
776                                 hash_destroy();
777                         }
778
779                         /*-------- DEBUG LOG --------*/
780                         if (sslid_protomod.get_log_level != NULL &&
781                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
782                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,30, "free: %p",
783                                     sslid_service_list[service_number]);
784                         }
785                         /*------ DEBUG LOG END ------*/
786
787                         free(sslid_service_list[service_number]);
788                         sslid_service_list[service_number] = NULL;
789
790                         free_flag = 1;
791                         break;
792                 }
793         }
794         
795         /* sslid service was not found */
796         if (free_flag == 0) {
797                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,100, "Could not find such service handle's sslid service.");
798                 return_value = -1;
799                 goto destroy_out;
800         }
801
802 destroy_out:
803         /*-------- DEBUG LOG --------*/
804         if (sslid_protomod.get_log_level != NULL &&
805             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
806                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116,
807                     "out_function: int destroy(handle_t srv_handle):return_value=%d",
808                     srv_handle);
809         }
810         /*------ DEBUG LOG END ------*/
811
812         return return_value;
813 }
814
815 /*!
816  * Destroy sslid service argument
817  * @param[in] sslid_arg sslid service argument
818  * @return void
819  */
820 static void
821 destroy_sa(void** sslid_arg)
822 {
823         /*-------- DEBUG LOG --------*/
824         if (sslid_protomod.get_log_level != NULL &&
825             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
826                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
827                 if (sslid_arg != NULL) {
828                         l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) *sslid_arg);
829                 }
830                 else {
831                         strncpy(sslid_arg_str, "NULL", DEBUG_STR_LEN);
832                 }
833                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,117,
834                     "in_function: void destroy_sa(void** sslid_arg):sslid_arg=&(&(%s))",
835                     sslid_arg_str);
836         }
837         /*------ DEBUG LOG END ------*/
838
839         /* check null */
840         if (sslid_arg == NULL) {
841                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,101, "Arg(sslid_arg) is NULL pointer.");
842         }
843         else if (*sslid_arg == NULL) {
844                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,102, "Arg(*sslid_arg) is NULL pointer.");
845         }
846         else {
847                 /*-------- DEBUG LOG --------*/
848                 if (sslid_protomod.get_log_level != NULL &&
849                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
850                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,31, "free: %p",
851                             *sslid_arg);
852                 }
853                 /*------ DEBUG LOG END ------*/
854
855                 /* free and NULL */
856                 free((struct l7vs_sslid_service_arg*) *sslid_arg);
857                 *sslid_arg = NULL;
858         }
859
860         /*-------- DEBUG LOG --------*/
861         if (sslid_protomod.get_log_level != NULL &&
862             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
863                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,118,
864                     "out_function: void destroy_sa(void** sslid_arg)");
865         }
866         /*------ DEBUG LOG END ------*/
867 }
868
869 /*!
870  * Create strings for service list of l7vsadm
871  * @param[out] srv_arg_mt service argument struct
872  * @param[in]  srv_handle a unique service ID
873  * @retval 0  successfully create strings
874  * @retval -1 some errors occur.
875  */
876 static int
877 service_arg(struct l7vs_service_arg_multi* srv_arg_mt, handle_t srv_handle)
878 {
879         struct l7vs_sslid_service* sslid_service;
880         struct l7vs_sslid_service_arg s_sarg;
881         char sslid_argument[SERVICE_ARG_MAXSIZE];
882         int return_value = 0;
883
884         /*-------- DEBUG LOG --------*/
885         if (sslid_protomod.get_log_level != NULL &&
886             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
887                 char srv_arg_mt_str[DEBUG_STR_LEN] = {0};
888                 l7vs_service_arg_multi_c_str(srv_arg_mt_str, srv_arg_mt);
889                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,119,
890                     "in_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
891                     "handle_t srv_handle):srv_arg_mt=&(%s), srv_handle=%u",
892                     srv_arg_mt_str, srv_handle);
893         }
894         /*------ DEBUG LOG END ------*/
895
896         /* check null */
897         if (srv_arg_mt == NULL) {
898                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,103, "Arg(srv_arg_mt) is NULL pointer.");
899                 return_value = -1;
900                 goto service_arg_out;
901         }
902
903         /* search service that has such a service ID */
904         sslid_service = l7vs_protomod_sslid_search_service(srv_handle);
905
906         /*-------- DEBUG LOG --------*/
907         if (sslid_protomod.get_log_level != NULL &&
908             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
909                 char sslid_str[DEBUG_STR_LEN] = {0};
910                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
911                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,120, "pointer assign: sslid_service=&(%s)",
912                     sslid_str);
913         }
914         /*------ DEBUG LOG END ------*/
915
916         if (sslid_service == NULL) {
917                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,104, "Could not find such service handle's sslid service.");
918                 return_value = -1;
919                 goto service_arg_out;
920         }
921
922         /* initialize argument strings */
923         memset(sslid_argument, 0, SERVICE_ARG_MAXSIZE);
924
925         /* set sslid args to service argument struct */
926         srv_arg_mt->srv_arg.reschedule = sslid_service->reschedule;
927
928         /* create long argument (l7vsadm option -l) */
929         strncpy(srv_arg_mt->srv_arg.protomod_key_string, sslid_argument, 256);
930
931         /* create verbose argument (l7vsadm option -V) */
932         snprintf(sslid_argument + strlen(sslid_argument), SERVICE_ARG_MAXSIZE - strlen(sslid_argument),
933             "--timeout %d --maxlist %d", sslid_service->timeout, sslid_service->maxlist);
934         strncpy(srv_arg_mt->srv_arg.protomod_opt_string, sslid_argument, 512);
935
936         /* set option value */
937         s_sarg.timeout = sslid_service->timeout;
938         s_sarg.maxlist = sslid_service->maxlist;
939         s_sarg.reschedule = sslid_service->reschedule;
940
941         memcpy(srv_arg_mt->protomod_arg, &s_sarg, sizeof(struct l7vs_sslid_service_arg));
942
943         /*-------- DEBUG LOG --------*/
944         if (sslid_protomod.get_log_level != NULL &&
945             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
946                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
947                 l7vs_sslid_service_arg_c_str(sslid_arg_str, &s_sarg);
948                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,121,
949                     "pointer assign: srv_arg_mt->protomod_arg=&(%s)", sslid_arg_str);
950         }
951         /*------ DEBUG LOG END ------*/
952
953 service_arg_out:
954         /*-------- DEBUG LOG --------*/
955         if (sslid_protomod.get_log_level != NULL &&
956             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
957                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,122,
958                     "out_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
959                     "handle_t srv_handle):return_value=%d", return_value);
960         }
961         /*------ DEBUG LOG END ------*/
962
963         return return_value;
964 }
965
966 /*!
967  * Parse l7vsadm options to sslid argument
968  * @param[out] sslid_arg sslid service argument struct
969  * @param[in]  argc      number of l7vsadm argument
970  * @param[in]  argv      l7vsadm argument list
971  * @retval 0  successfully parse argument
972  * @retval -1 some errors occur.
973  */
974 static int
975 parse(void* sslid_arg, int argc, char* argv[])
976 {
977         struct l7vs_sslid_service_arg* sslid_service_arg;
978         static struct option opt[] = {
979                 {"timeout",    required_argument, NULL, 'T'},
980                 {"maxlist",        required_argument, NULL, 'M'},
981                 {"reschedule",             no_argument,       NULL, 'R'},
982                 {"no-reschedule",          no_argument,       NULL, 'N'},
983                 {NULL,                     0,                 NULL, 0  }
984         };
985         int c;
986         unsigned long buffer;
987         int timeout_flag = 0;
988         int maxlist_flag = 0;
989         int reschedule_flag = 0;
990         int return_value = 0;
991
992         /*-------- DEBUG LOG --------*/
993         if (sslid_protomod.get_log_level != NULL &&
994             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
995                 int i;
996                 char argv_str[DEBUG_STR_LEN] = {0};
997                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
998                 l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) sslid_arg);
999                 argv_str[0] = '\0';
1000                 if (argv == NULL)
1001                         snprintf(argv_str, DEBUG_STR_LEN, "NULL");
1002                 else {
1003                         for (i = 0; i < argc; i++) {
1004                                 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1005                         }
1006                         i = strnlen(argv_str, DEBUG_STR_LEN);
1007                         if (i > 1)
1008                                 argv_str[i - 2] = '\0';
1009                 }
1010                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,123,
1011                     "in_function: int parse(void* sslid_arg, int argc, char* argv[]):sslid_arg=&(%s), "
1012                     "argc=%d, %s", sslid_arg_str, argc, argv_str);
1013         }
1014         /*------ DEBUG LOG END ------*/
1015
1016         /* check null */
1017         if (sslid_arg == NULL) {
1018                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105, "Arg(sslid_arg) is NULL pointer.");
1019                 return_value = -1;
1020                 goto parse_out;
1021         }
1022         if (argv == NULL) {
1023                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,106, "Arg(argv) is NULL pointer.");
1024                 return_value = -1;
1025                 goto parse_out;
1026         }
1027
1028         sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
1029         optind = 0;
1030
1031         /* check all argument */
1032         while ((c = getopt_long(argc, argv, "T:M:RN", opt, NULL)) != -1) {
1033                 switch (c) {
1034                 /* --timeout / -T */
1035                 case 'T':
1036                         if (sscanf(optarg, "%lu", &buffer) == 0) {
1037                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
1038                                     "-T/--timeout option value '%s' is invalid.", optarg);
1039                                 return_value = -1;
1040                                 goto parse_out;
1041                         }
1042                         if (buffer > INT_MAX) {
1043                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
1044                                     "-T/--timeout option value '%s' is too large.", optarg);
1045                                 return_value = -1;
1046                                 goto parse_out;
1047                         }
1048                         else
1049                                 sslid_service_arg->timeout = buffer;
1050                         timeout_flag++;
1051                         break;
1052
1053                 /* --maxlist / -M */
1054                 case 'M':
1055                         if (sscanf(optarg, "%lu", &buffer) == 0) {
1056                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109,
1057                                     "-M/--maxlist option value '%s' is invalid.", optarg);
1058                                 return_value = -1;
1059                                 goto parse_out;
1060                         }
1061                         if (buffer > INT_MAX) {
1062                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110,
1063                                     "-M/--maxlist option value '%s' is too large.", optarg);
1064                                 return_value = -1;
1065                                 goto parse_out;
1066                         }
1067                         else
1068                                 sslid_service_arg->maxlist = buffer;
1069                         maxlist_flag++;
1070                         break;
1071
1072                 /* --reschedule / -R */
1073                 case 'R':
1074                         /* reschedule on */
1075                         sslid_service_arg->reschedule = 1;
1076                         reschedule_flag++;
1077                         break;
1078
1079                 /* --no-reschedule / -N */
1080                 case 'N':
1081                         /* reschedule off */
1082                         sslid_service_arg->reschedule = 0;
1083                         reschedule_flag++;
1084                         break;
1085
1086                 /* else error */
1087                 default:
1088                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111, "Option error.");
1089                         return_value = -1;
1090                         goto parse_out;
1091                 }
1092         }
1093
1094         /* when set both -R and -N at the same time */
1095         if (reschedule_flag > 1) {
1096                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,112,
1097                     "You should choose either reschdule or no-reschedule.");
1098                 return_value = -1;
1099                 goto parse_out;
1100         }
1101         /* same option */
1102         if (timeout_flag > 1) {
1103                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,113,
1104                     "Cannot set multiple option '--timeout/-T'.");
1105                 return_value = -1;
1106                 goto parse_out;
1107         }
1108         if (maxlist_flag > 1) {
1109                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
1110                     "Cannot set multiple option '--maxlist/-M'.");
1111                 return_value = -1;
1112                 goto parse_out;
1113         }
1114
1115         /* set default no reschedule */
1116         if (reschedule_flag == 0) {
1117                 sslid_service_arg->reschedule = 0;
1118         }
1119
1120         /* set default options */
1121         if (timeout_flag == 0) {
1122                 sslid_service_arg->timeout = 3600;
1123         }
1124         if (maxlist_flag == 0 || sslid_service_arg->maxlist == 0) {
1125                 sslid_service_arg->maxlist = 1024;
1126         }
1127
1128 parse_out:
1129         /*-------- DEBUG LOG --------*/
1130         if (sslid_protomod.get_log_level != NULL &&
1131             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1132                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,124,
1133                     "out_function: int parse(void* sslid_arg, int argc, char* argv[]):return_value=%d",
1134                     return_value);
1135         }
1136         /*------ DEBUG LOG END ------*/
1137
1138         return return_value;
1139 }
1140
1141 /*!
1142  * Search sslid service from sslid service list using service handle
1143  * @param[in] service_handle a unique service ID
1144  * @return sslid service struct when service was found. NULL when service was not found.
1145  */
1146 static struct l7vs_sslid_service*
1147 l7vs_protomod_sslid_search_service(handle_t service_handle)
1148 {
1149         /* sslid service list counter */
1150         int service_number = 0;
1151         struct l7vs_sslid_service* return_value = NULL;
1152
1153         /*-------- DEBUG LOG --------*/
1154         if (sslid_protomod.get_log_level != NULL &&
1155             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1156                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,125,
1157                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1158                     "service_handle=%d", service_handle);
1159         }
1160         /*------ DEBUG LOG END ------*/
1161
1162         /* check all sslid service list */
1163         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
1164                 /* found the service has same service handle */
1165                 if (sslid_service_list[service_number] != NULL && 
1166                     sslid_service_list[service_number]->service_handle == service_handle) {
1167                         return_value = sslid_service_list[service_number];
1168                         break;
1169                 }
1170         }
1171         
1172         /*-------- DEBUG LOG --------*/
1173         if (sslid_protomod.get_log_level != NULL &&
1174             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1175                 char ssl_str[DEBUG_STR_LEN] = {0};
1176                 l7vs_sslid_service_c_str(ssl_str, return_value);
1177                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,126,
1178                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1179                     "return_value=&(%s)", ssl_str);
1180         }
1181         /*------ DEBUG LOG END ------*/
1182
1183         return return_value;
1184 }
1185
1186 /*!
1187  * Create sslid service.
1188  * @param  void
1189  * @return sslid service struct when create a service. NULL when cannot create service.
1190  */
1191 static struct l7vs_sslid_service*
1192 l7vs_protomod_sslid_create_service()
1193 {
1194         int service_number = 0;
1195         struct l7vs_sslid_service* return_value = NULL;
1196
1197         /*-------- DEBUG LOG --------*/
1198         if (sslid_protomod.get_log_level != NULL &&
1199             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1200                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,127,
1201                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service()");
1202         }
1203         /*------ DEBUG LOG END ------*/
1204
1205         /* check all sslid service list */
1206         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER - 1; ++service_number) {
1207                 /* if pointer that does not point NULL exists ... */
1208                 if (sslid_service_list[service_number] == NULL) {
1209                         /* create a service at empty pointer */
1210                         sslid_service_list[service_number] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1211
1212                         /*-------- DEBUG LOG --------*/
1213                         if (sslid_protomod.get_log_level != NULL &&
1214                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1215                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,32, "calloc: addr=%p, size=%ld",
1216                                     sslid_service_list[service_number], (unsigned long int) sizeof(struct l7vs_sslid_service));
1217                         }
1218                         /*------ DEBUG LOG END ------*/
1219
1220                         if (sslid_service_list[service_number] == NULL) {
1221                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,25, "Could not allocate memory.");
1222                                 goto create_service_out;
1223                         }
1224                         return_value = sslid_service_list[service_number];
1225                         goto create_service_out;
1226                 }
1227         }
1228         
1229         /* all service list is full */
1230         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115, "sslid service list is full.");
1231
1232 create_service_out:
1233         /*-------- DEBUG LOG --------*/
1234         if (sslid_protomod.get_log_level != NULL &&
1235             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1236                 char ssl_str[DEBUG_STR_LEN] = {0};
1237                 l7vs_sslid_service_c_str(ssl_str, return_value);
1238                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,128,
1239                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1240                     "return_value=&(%s)", ssl_str);
1241         }
1242         /*------ DEBUG LOG END ------*/
1243
1244         return return_value;
1245 }
1246
1247 /*!
1248  * Create temporary sslid service.
1249  * @param  void
1250  * @return sslid service struct when create a service. NULL when cannot create service.
1251  */
1252 static struct l7vs_sslid_service*
1253 l7vs_protomod_sslid_create_temp_service()
1254 {
1255         struct l7vs_sslid_service* return_value = NULL;
1256
1257         /*-------- DEBUG LOG --------*/
1258         if (sslid_protomod.get_log_level != NULL &&
1259             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1260                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,129,
1261                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_temp_service()");
1262         }
1263         /*------ DEBUG LOG END ------*/
1264
1265         /* if pointer that does not point NULL exists ... */
1266         if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] != NULL) {
1267                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116, "Temporary sslid service is being used by other process.");
1268                 goto create_temp_service_out;
1269         }
1270
1271         /* create temp service */
1272         sslid_service_list[SSLID_SERVICE_NUMBER - 1] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1273
1274         /*-------- DEBUG LOG --------*/
1275         if (sslid_protomod.get_log_level != NULL &&
1276             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1277                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,33, "calloc: addr=%p, size=%ld",
1278                     sslid_service_list[SSLID_SERVICE_NUMBER - 1], (unsigned long int) sizeof(struct l7vs_sslid_service));
1279         }
1280         /*------ DEBUG LOG END ------*/
1281
1282         if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] == NULL) {
1283                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,26, "Could not allocate memory");
1284                 goto create_temp_service_out;
1285         }
1286
1287         return_value = sslid_service_list[SSLID_SERVICE_NUMBER - 1];
1288
1289 create_temp_service_out:
1290         /*-------- DEBUG LOG --------*/
1291         if (sslid_protomod.get_log_level != NULL &&
1292             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1293                 char ssl_str[DEBUG_STR_LEN] = {0};
1294                 l7vs_sslid_service_c_str(ssl_str, return_value);
1295                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,130,
1296                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1297                     "return_value=&(%s)", ssl_str);
1298         }
1299         /*------ DEBUG LOG END ------*/
1300
1301         return return_value;
1302 }
1303
1304 /*!
1305  * Read replication area and set session data.
1306  * @param[in] sslid_service read this sslid service's session.
1307  * @return void
1308  */
1309 static void l7vs_protomod_sslid_read_replication_data(struct l7vs_sslid_service* sslid_service, struct l7vs_service* srv)
1310 {
1311         struct replication_header* head;
1312         struct replication_header* pick = NULL;
1313         unsigned int data_size = 0;
1314         unsigned int used = 0;
1315         void* data_addr = NULL;
1316         char exist = -1;
1317         int srv_num;
1318
1319         /*-------- DEBUG LOG --------*/
1320         if (sslid_protomod.get_log_level != NULL &&
1321             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1322                 char ssl_str[DEBUG_STR_LEN] = {0};
1323                 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1324                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,131,
1325                     "in_function: void l7vs_protomod_sslid_read_replication_data(struct "
1326                     "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1327         }
1328         /*------ DEBUG LOG END ------*/
1329
1330         /* check null */
1331         if (sslid_service == NULL) {
1332                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1333                 goto read_replication_data_out;
1334         }
1335         if (sslid_service->session == NULL) {
1336                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1337                 goto read_replication_data_out;
1338         }
1339         if (srv == NULL) {
1340                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1341                     "Service that has handle(%d) is not found.", sslid_service->service_handle);
1342                 goto read_replication_data_out;
1343         }
1344         if (srv->lsock == NULL) {
1345                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1346                     "Conn of service that has handle(%d) is NULL pointer.", sslid_service->service_handle);
1347                 goto read_replication_data_out;
1348         }
1349
1350         /* get replication area address */
1351         data_addr = sslid_protomod.replication_pay_memory(sslid_protomod.modname, &data_size);
1352         if (data_addr == NULL || data_size <= 0)
1353                 goto read_replication_data_out;
1354
1355         /* check replication area header */
1356         for (srv_num = 0; srv_num < SSLID_SERVICE_NUMBER; srv_num++) {
1357                 head = (struct replication_header*) data_addr + srv_num;
1358                 used += head->size;
1359
1360                 if (data_size * DATA_SIZE < sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used) {
1361                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Over replication area.");
1362                         goto read_replication_data_out;
1363                 }
1364
1365                 if (pick == NULL && head->size == 0)
1366                         pick = head;
1367                 if (exist >= 0 && pick != NULL)
1368                         break;
1369
1370                 /* match ip and port, this is pre-used session information */
1371                 if (memcmp(&head->sin_addr, &srv->lsock->addr.sin_addr, sizeof(struct in_addr)) == 0 &&
1372                     head->sin_port == srv->lsock->addr.sin_port) {
1373                         exist = srv_num;
1374                 }
1375         }
1376
1377         if (exist >= 0) {
1378                 head = (struct replication_header*) data_addr + exist;
1379
1380                 /* restore session information */
1381                 if (sslid_service->maxlist * sizeof(struct ssl_session) > head->size) {
1382                         // resize if maxlist set bigger than old
1383                         if (pick != NULL) {
1384                                 /* area size check */
1385                                 if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1386                                     used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1387                                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1388                                             "Replication area is full.");
1389                                         goto read_replication_data_out;
1390                                 }
1391                                 else {
1392                                         memcpy(sslid_service->session, (char*) data_addr + head->offset, head->size);
1393                                         memset(sslid_service->replication_addr, 0, head->size);
1394                                         sslid_service->replication_addr = (char*) data_addr +
1395                                             sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1396                                         pick->sin_addr = srv->lsock->addr.sin_addr;
1397                                         pick->sin_port = srv->lsock->addr.sin_port;
1398                                         pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1399                                         pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1400
1401                                         /*-------- DEBUG LOG --------*/
1402                                         if (sslid_protomod.get_log_level != NULL &&
1403                                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1404                                                 char head_str[DEBUG_STR_LEN];
1405                                                 replication_header_c_str(head_str, pick);
1406                                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1407                                                     "Write replication area: head=(%s)", head_str);
1408                                         }
1409                                         /*------ DEBUG LOG END ------*/
1410
1411                                         // you should garbage old session area...
1412                                 }
1413                         }
1414                         else {
1415                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1416                                     "Replication area is full.");
1417                                 goto read_replication_data_out;
1418                         }
1419                 }
1420                 else {
1421                         sslid_service->replication_addr = (char*) data_addr + head->offset;
1422                         memcpy(sslid_service->session, sslid_service->replication_addr,
1423                             sslid_service->maxlist * sizeof(struct ssl_session));
1424                         head->size = sslid_service->maxlist * sizeof(struct ssl_session);
1425
1426                         /*-------- DEBUG LOG --------*/
1427                         if (sslid_protomod.get_log_level != NULL &&
1428                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1429                                 char head_str[DEBUG_STR_LEN];
1430                                 replication_header_c_str(head_str, head);
1431                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1432                                     "Write replication area: head=(%s)", head_str);
1433                         }
1434                         /*------ DEBUG LOG END ------*/
1435                 }
1436         }
1437
1438         if (exist == -1) {
1439                 if (pick != NULL) {
1440                         /* area size check */
1441                         if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1442                             used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1443                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1444                                     "Replication area is full.");
1445                                 goto read_replication_data_out;
1446                         }
1447                         else {
1448                                 /* initialize replication information */
1449                                 sslid_service->replication_addr = (char*) data_addr +
1450                                     sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1451                                 pick->sin_addr = srv->lsock->addr.sin_addr;
1452                                 pick->sin_port = srv->lsock->addr.sin_port;
1453                                 pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1454                                 pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1455
1456                                 /*-------- DEBUG LOG --------*/
1457                                 if (sslid_protomod.get_log_level != NULL &&
1458                                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1459                                         char head_str[DEBUG_STR_LEN];
1460                                         replication_header_c_str(head_str, pick);
1461                                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1462                                             "Write replication area: head=(%s)", head_str);
1463                                 }
1464                                 /*------ DEBUG LOG END ------*/
1465                         }
1466                 }
1467                 else {
1468                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1469                             "Replication area is full.");
1470                         goto read_replication_data_out;
1471                 }
1472         }
1473
1474 read_replication_data_out:
1475         /*-------- DEBUG LOG --------*/
1476         if (sslid_protomod.get_log_level != NULL &&
1477             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1478                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,132,
1479                     "out_function: l7vs_protomod_sslid_read_replication_data(struct "
1480                     "l7vs_sslid_service* sslid_service)");
1481         }
1482         /*------ DEBUG LOG END ------*/
1483 }
1484
1485 /*!
1486  * Write session data to replication area.
1487  * @param[in] sslid_service save this sslid service's session.
1488  * @return void
1489  */
1490 static void l7vs_protomod_sslid_write_replication_data(struct l7vs_sslid_service* sslid_service)
1491 {
1492         /*-------- DEBUG LOG --------*/
1493         if (sslid_protomod.get_log_level != NULL &&
1494             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1495                 char ssl_str[DEBUG_STR_LEN] = {0};
1496                 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1497                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,133,
1498                     "in_function: void l7vs_protomod_sslid_write_replication_data(struct "
1499                     "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1500         }
1501         /*------ DEBUG LOG END ------*/
1502
1503         /* check null */
1504         if (sslid_service == NULL) {
1505                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1506                 goto write_replication_data_out;
1507         }
1508         if (sslid_service->session == NULL) {
1509                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1510                 goto write_replication_data_out;
1511         }
1512         /* no replicate setting */
1513         if (sslid_service->replication_addr == NULL) {
1514                 goto write_replication_data_out;
1515         }
1516
1517         /* copy session data */
1518         memcpy(sslid_service->replication_addr, sslid_service->session,
1519             sizeof(struct ssl_session) * sslid_service->maxlist);
1520
1521         /*-------- DEBUG LOG --------*/
1522         if (sslid_protomod.get_log_level != NULL &&
1523             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1524                 char session_str[DEBUG_STR_LEN];
1525                 ssl_session_c_str(session_str, (struct ssl_session*) sslid_service->replication_addr);
1526                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Write replication area: session=(%s)",
1527                     session_str);
1528         }
1529         /*------ DEBUG LOG END ------*/
1530
1531 write_replication_data_out:
1532         /*-------- DEBUG LOG --------*/
1533         if (sslid_protomod.get_log_level != NULL &&
1534             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1535                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,134,
1536                     "out_function: void l7vs_protomod_sslid_write_replication_data(struct "
1537                     "l7vs_sslid_service* sslid_service)");
1538         }
1539         /*------ DEBUG LOG END ------*/
1540 }
1541
1542 /*!
1543  * Serialize struct l7vs_sslid_service for debug log.
1544  * @param[out] buf   serialized string
1545  * @param[in]  sslid l7vs_sslid_service struct
1546  */
1547 static void l7vs_sslid_service_c_str(char* buf, struct l7vs_sslid_service* sslid) {
1548         if (sslid == NULL) {
1549                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1550         }
1551         else {
1552                 char session_str[DEBUG_STR_LEN] = {0};
1553                 ssl_session_c_str(session_str, sslid->session);
1554                 snprintf(buf, DEBUG_STR_LEN, "service_handle=%d, timeout=%d, maxlist=%d, "
1555                     "session=(%s), replication_addr=%p, reschedule=%d", sslid->service_handle,
1556                     sslid->timeout, sslid->maxlist, session_str, sslid->replication_addr,
1557                     sslid->reschedule);
1558         }
1559 }
1560
1561 /*!
1562  * Serialize struct l7vs_sslid_service_arg for debug log.
1563  * @param[out] buf       serialized string
1564  * @param[in]  sslid_arg l7vs_sslid_service_arg struct
1565  */
1566 void l7vs_sslid_service_arg_c_str(char* buf, struct l7vs_sslid_service_arg* sslid_arg) {
1567         if (sslid_arg == NULL) {
1568                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1569         }
1570         else {
1571                 snprintf(buf, DEBUG_STR_LEN, "timeout=%d, maxlist=%d, reschedule=%d",
1572                     sslid_arg->timeout, sslid_arg->maxlist, sslid_arg->reschedule);
1573         }
1574 }
1575
1576 /*!
1577  * Serialize struct ssl_session for debug log.
1578  * @param[out] buf     serialized string
1579  * @param[in]  session ssl_session struct
1580  */
1581 static void ssl_session_c_str(char* buf, struct ssl_session* session) {
1582         if (session == NULL) {
1583                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1584         }
1585         else {
1586                 char dest_str[DEBUG_STR_LEN] = {0};
1587                 char session_str[SSLID_LENGTH * 2 + 1];
1588                 l7vs_dest_c_str(dest_str, &session->dest);
1589                 id_c_str(session_str, session->id);
1590                 snprintf(buf, DEBUG_STR_LEN, "id=%s, dest=(%s), last_time=%d, valid=%d",
1591                     session_str, dest_str, (u_int) session->last_time, (int)session->valid);
1592         }
1593 }
1594
1595 /*!
1596  * Serialize struct replication_header for debug log.
1597  * @param[out] buf  serialized string
1598  * @param[in]  head replication_header struct
1599  */
1600 static void replication_header_c_str(char* buf, struct replication_header* head) {
1601         if (head == NULL) {
1602                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1603         }
1604         else {
1605                 snprintf(buf, DEBUG_STR_LEN, "sin_addr=(s_addr=%ld), sin_port=%d, size=%d, offset=%d",
1606                     (u_long) head->sin_addr.s_addr, head->sin_port, head->size, head->offset);
1607         }
1608 }
1609
1610 /*!
1611  * Convert SSL session ID (binary to hex)
1612  * @param[out] buf hex string
1613  * @param[in]  id  SSL session ID
1614  */
1615 static void id_c_str(char* buf, char* id) {
1616         int i;
1617         if (id == NULL) {
1618                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1619         }
1620         else {
1621                 for (i = 0; i < SSLID_LENGTH; i++) {
1622                         snprintf(buf + i * 2, DEBUG_STR_LEN - i * 2, "%02X", (unsigned int)id[i]);
1623                 }
1624         }
1625 }