OSDN Git Service

Merge commit 'origin/rcscript-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         l7vs_protomod_sslid_read_replication_data(sslid_service, srv);
517         hash_rebuild_sessionlist(sslid_service);
518
519         /* initialize protocol module ... clear destination list */
520         ret = srv->pm->initialize(srv, conn, request, *len, dest);
521         if (ret != 0){
522                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,91, "Could not initialize protomod.");
523                 return_value = -1;
524                 goto match_cldata_out;
525         }
526
527         /* check payload */
528         if (
529             *len > 75 &&
530             (
531              (request[1] == 0x03 && request[2] == 0x00 && request[9] == 0x03 && request [10] == 0x00) || // SSL v3
532              (request[1] == 0x03 && request[2] == 0x01 && request[9] == 0x03 && request [10] == 0x01)    // TLS v1
533             ) &&
534             request[5] == 0x01 && // Client Hello
535             request[43] == 0x20 // Session ID Length
536            ) {
537                 /*-------- DEBUG LOG --------*/
538                 if (sslid_protomod.get_log_level != NULL &&
539                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
540                         char id_str[DEBUG_STR_LEN] = {0};
541                         id_c_str(id_str, &request[44]);
542                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105,
543                             "Client Hello/SessionID=%s", id_str);
544                 }
545                 /*------ DEBUG LOG END ------*/
546
547                 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
548                 id_c_str(id_str, &request[44]);
549                 searchret = hash_search(id_str, &tmpdest);
550                 
551                 if (searchret == 0) {
552                         *dest = tmpdest;
553                 }
554                 
555         }
556
557         *tcps = 0;
558
559         /* finalize, always set reschedule flag */
560         ret = srv->pm->finalize(srv, conn, request, *len, dest, sslid_service->reschedule);
561         if (ret != 0){
562                 PUT_LOG_INFO(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,11, "Could not finalize protomod. (Realserver decision failure)");
563                 return_value = -1;
564                 goto match_cldata_out;
565         }
566
567 match_cldata_out:
568         /*-------- DEBUG LOG --------*/
569         if (sslid_protomod.get_log_level != NULL &&
570             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
571                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
572                     "out_function: int match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
573                     "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):return_value=%d",
574                     return_value);
575         }
576         /*------ DEBUG LOG END ------*/
577
578         return return_value;
579 }
580
581 /*!
582  * Check and modify response packet.
583  * @param[in] srv      service struct include service handle, protocol module and schedule module.
584  * @param[in] conn     connection data.
585  * @param[in] response packet data from real server
586  * @param[in] len      length of packet data. it will be lengthened.
587  * @retval 0  successfully check packet data.
588  * @retval -1 some errors occur.
589  */
590 static int
591 analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn,
592         char* response, size_t* len)
593 {
594         struct l7vs_sslid_service* sslid_service;
595         int exist = 0;
596         int return_value = 0;
597         int i;
598         int pick;
599         time_t now, oldest = 0;
600         char session_full = 1;
601         char id_str[DEBUG_STR_LEN] = {0};
602
603         /*-------- DEBUG LOG --------*/
604         if (sslid_protomod.get_log_level != NULL &&
605             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
606                 char srv_str[DEBUG_STR_LEN] = {0};
607                 char conn_str[DEBUG_STR_LEN] = {0};
608                 char len_str[DEBUG_STR_LEN] = {0};
609                 l7vs_service_c_str(srv_str, srv);
610                 l7vs_conn_c_str(conn_str, conn);
611                 if (len != NULL) {
612                         snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
613                 }
614                 else {
615                         strncpy(len_str, "NULL", DEBUG_STR_LEN);
616                 }
617                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
618                     "in_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
619                     "char* response, size_t* len):srv=&(%s), conn=&(%s), response=\"%s\", len=&(%s)",
620                     srv_str, conn_str, response, len_str);
621         }
622         /*------ DEBUG LOG END ------*/
623
624         /* check null */
625         if (srv == NULL) {
626                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,93, "Arg(srv) is NULL pointer.");
627                 return_value = -1;
628                 goto analyze_rsdata_out;
629         }
630         if (conn == NULL) {
631                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,94, "Arg(conn) is NULL pointer.");
632                 return_value = -1;
633                 goto analyze_rsdata_out;
634         }
635         if (conn->dest == NULL) {
636                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,95, "Arg(conn->dest) is NULL pointer.");
637                 return_value = -1;
638                 goto analyze_rsdata_out;
639         }
640         if (response == NULL) {
641                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,96, "Arg(response) is NULL pointer.");
642                 return_value = -1;
643                 goto analyze_rsdata_out;
644         }
645         if (len == NULL) {
646                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,97, "Arg(len) is NULL pointer.");
647                 return_value = -1;
648                 goto analyze_rsdata_out;
649         }
650
651         /* sorry flag check */
652         if (conn->sorry_conn_flag == 1) {
653                 /*-------- DEBUG LOG --------*/
654                 if (sslid_protomod.get_log_level != NULL &&
655                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
656                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109, "Response from sorry server.");
657                 }
658                 /*------ DEBUG LOG END ------*/
659
660                 goto analyze_rsdata_out;
661         }
662
663         /* search service that has such a service ID */
664         sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
665
666         /*-------- DEBUG LOG --------*/
667         if (sslid_protomod.get_log_level != NULL &&
668             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
669                 char sslid_str[DEBUG_STR_LEN] = {0};
670                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
671                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110, "pointer assign: sslid_service=&(%s)",
672                     sslid_str);
673         }
674         /*------ DEBUG LOG END ------*/
675
676         if (sslid_service == NULL) {
677                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,98,
678                     "Could not find such service handle's sslid service.");
679                 return_value = -1;
680                 goto analyze_rsdata_out;
681         }
682         if (sslid_service->session == NULL) {
683                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,99,
684                     "Service has NULL pointer session.");
685                 return_value = -1;
686                 goto analyze_rsdata_out;
687         }
688
689         /* check payload */
690         if (
691             *len > 75 &&
692             (
693              (response[1] == 0x03 && response[2] == 0x00 && response[9] == 0x03 && response [10] == 0x00) || // SSL v3
694              (response[1] == 0x03 && response[2] == 0x01 && response[9] == 0x03 && response [10] == 0x01)    // TLS v1
695             ) &&
696             response[5]  == 0x02 && // Server Hello
697             response[43] == 0x20 // Session ID Length
698            ) {
699                 /*-------- DEBUG LOG --------*/
700                 if (sslid_protomod.get_log_level != NULL &&
701                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
702                         char id_str[DEBUG_STR_LEN] = {0};
703                         id_c_str(id_str, &response[44]);
704                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111,
705                             "Server Hello/SessionID=%s", id_str);
706                 }
707                 /*------ DEBUG LOG END ------*/
708
709                 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
710                 id_c_str(id_str, &response[44]);
711                 hash_add(id_str, *conn->dest);
712                 hash_construct_sessionlist(sslid_service);
713                 l7vs_protomod_sslid_write_replication_data(sslid_service);
714         }
715
716 analyze_rsdata_out:
717         /*-------- DEBUG LOG --------*/
718         if (sslid_protomod.get_log_level != NULL &&
719             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
720                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
721                     "out_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
722                     "char* response, size_t* len):return_value=%d", return_value);
723         }
724         /*------ DEBUG LOG END ------*/
725
726         return return_value;
727 }
728
729 /*!
730  * Destroy sslid service
731  * @param[in] srv_handle a unique service ID
732  * @retval 0  successfully check packet data.
733  * @retval -1 some errors occur.
734  */
735 static int
736 destroy(handle_t srv_handle)
737 {
738         /* sslid service list counter */
739         int service_number = 0;
740         int free_flag = 0;
741         int return_value = 0;
742
743         /*-------- DEBUG LOG --------*/
744         if (sslid_protomod.get_log_level != NULL &&
745             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
746                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115,
747                     "in_function: int destroy(handle_t srv_handle):srv_handle=%u",
748                     srv_handle);
749         }
750         /*------ DEBUG LOG END ------*/
751
752         /* check all sslid service list */
753         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
754                 /* found sslid service that has srv_handle */
755                 if (sslid_service_list[service_number] != NULL && 
756                     sslid_service_list[service_number]->service_handle == srv_handle) {
757
758                         /* free and NULL */
759                         if (sslid_service_list[service_number]->session != NULL) {
760
761                                 /*-------- DEBUG LOG --------*/
762                                 if (sslid_protomod.get_log_level != NULL &&
763                                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
764                                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,29, "free: %p",
765                                             sslid_service_list[service_number]->session);
766                                 }
767                                 /*------ DEBUG LOG END ------*/
768
769                                 free(sslid_service_list[service_number]->session);
770                                 sslid_service_list[service_number]->session = NULL;
771                                 hash_setPointer(sslid_service_list[service_number]->hash_map, sslid_service_list[service_number]->hash_list, sslid_service_list[service_number]->maxlist);
772                                 hash_destroy();
773                         }
774
775                         /*-------- DEBUG LOG --------*/
776                         if (sslid_protomod.get_log_level != NULL &&
777                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
778                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,30, "free: %p",
779                                     sslid_service_list[service_number]);
780                         }
781                         /*------ DEBUG LOG END ------*/
782
783                         free(sslid_service_list[service_number]);
784                         sslid_service_list[service_number] = NULL;
785
786                         free_flag = 1;
787                         break;
788                 }
789         }
790         
791         /* sslid service was not found */
792         if (free_flag == 0) {
793                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,100, "Could not find such service handle's sslid service.");
794                 return_value = -1;
795                 goto destroy_out;
796         }
797
798 destroy_out:
799         /*-------- DEBUG LOG --------*/
800         if (sslid_protomod.get_log_level != NULL &&
801             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
802                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116,
803                     "out_function: int destroy(handle_t srv_handle):return_value=%d",
804                     srv_handle);
805         }
806         /*------ DEBUG LOG END ------*/
807
808         return return_value;
809 }
810
811 /*!
812  * Destroy sslid service argument
813  * @param[in] sslid_arg sslid service argument
814  * @return void
815  */
816 static void
817 destroy_sa(void** sslid_arg)
818 {
819         /*-------- DEBUG LOG --------*/
820         if (sslid_protomod.get_log_level != NULL &&
821             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
822                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
823                 if (sslid_arg != NULL) {
824                         l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) *sslid_arg);
825                 }
826                 else {
827                         strncpy(sslid_arg_str, "NULL", DEBUG_STR_LEN);
828                 }
829                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,117,
830                     "in_function: void destroy_sa(void** sslid_arg):sslid_arg=&(&(%s))",
831                     sslid_arg_str);
832         }
833         /*------ DEBUG LOG END ------*/
834
835         /* check null */
836         if (sslid_arg == NULL) {
837                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,101, "Arg(sslid_arg) is NULL pointer.");
838         }
839         else if (*sslid_arg == NULL) {
840                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,102, "Arg(*sslid_arg) is NULL pointer.");
841         }
842         else {
843                 /*-------- DEBUG LOG --------*/
844                 if (sslid_protomod.get_log_level != NULL &&
845                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
846                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,31, "free: %p",
847                             *sslid_arg);
848                 }
849                 /*------ DEBUG LOG END ------*/
850
851                 /* free and NULL */
852                 free((struct l7vs_sslid_service_arg*) *sslid_arg);
853                 *sslid_arg = NULL;
854         }
855
856         /*-------- DEBUG LOG --------*/
857         if (sslid_protomod.get_log_level != NULL &&
858             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
859                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,118,
860                     "out_function: void destroy_sa(void** sslid_arg)");
861         }
862         /*------ DEBUG LOG END ------*/
863 }
864
865 /*!
866  * Create strings for service list of l7vsadm
867  * @param[out] srv_arg_mt service argument struct
868  * @param[in]  srv_handle a unique service ID
869  * @retval 0  successfully create strings
870  * @retval -1 some errors occur.
871  */
872 static int
873 service_arg(struct l7vs_service_arg_multi* srv_arg_mt, handle_t srv_handle)
874 {
875         struct l7vs_sslid_service* sslid_service;
876         struct l7vs_sslid_service_arg s_sarg;
877         char sslid_argument[SERVICE_ARG_MAXSIZE];
878         int return_value = 0;
879
880         /*-------- DEBUG LOG --------*/
881         if (sslid_protomod.get_log_level != NULL &&
882             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
883                 char srv_arg_mt_str[DEBUG_STR_LEN] = {0};
884                 l7vs_service_arg_multi_c_str(srv_arg_mt_str, srv_arg_mt);
885                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,119,
886                     "in_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
887                     "handle_t srv_handle):srv_arg_mt=&(%s), srv_handle=%u",
888                     srv_arg_mt_str, srv_handle);
889         }
890         /*------ DEBUG LOG END ------*/
891
892         /* check null */
893         if (srv_arg_mt == NULL) {
894                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,103, "Arg(srv_arg_mt) is NULL pointer.");
895                 return_value = -1;
896                 goto service_arg_out;
897         }
898
899         /* search service that has such a service ID */
900         sslid_service = l7vs_protomod_sslid_search_service(srv_handle);
901
902         /*-------- DEBUG LOG --------*/
903         if (sslid_protomod.get_log_level != NULL &&
904             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
905                 char sslid_str[DEBUG_STR_LEN] = {0};
906                 l7vs_sslid_service_c_str(sslid_str, sslid_service);
907                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,120, "pointer assign: sslid_service=&(%s)",
908                     sslid_str);
909         }
910         /*------ DEBUG LOG END ------*/
911
912         if (sslid_service == NULL) {
913                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,104, "Could not find such service handle's sslid service.");
914                 return_value = -1;
915                 goto service_arg_out;
916         }
917
918         /* initialize argument strings */
919         memset(sslid_argument, 0, SERVICE_ARG_MAXSIZE);
920
921         /* set sslid args to service argument struct */
922         srv_arg_mt->srv_arg.reschedule = sslid_service->reschedule;
923
924         /* create long argument (l7vsadm option -l) */
925         strncpy(srv_arg_mt->srv_arg.protomod_key_string, sslid_argument, 256);
926
927         /* create verbose argument (l7vsadm option -V) */
928         snprintf(sslid_argument + strlen(sslid_argument), SERVICE_ARG_MAXSIZE - strlen(sslid_argument),
929             "--timeout %d --maxlist %d", sslid_service->timeout, sslid_service->maxlist);
930         strncpy(srv_arg_mt->srv_arg.protomod_opt_string, sslid_argument, 512);
931
932         /* set option value */
933         s_sarg.timeout = sslid_service->timeout;
934         s_sarg.maxlist = sslid_service->maxlist;
935         s_sarg.reschedule = sslid_service->reschedule;
936
937         memcpy(srv_arg_mt->protomod_arg, &s_sarg, sizeof(struct l7vs_sslid_service_arg));
938
939         /*-------- DEBUG LOG --------*/
940         if (sslid_protomod.get_log_level != NULL &&
941             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
942                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
943                 l7vs_sslid_service_arg_c_str(sslid_arg_str, &s_sarg);
944                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,121,
945                     "pointer assign: srv_arg_mt->protomod_arg=&(%s)", sslid_arg_str);
946         }
947         /*------ DEBUG LOG END ------*/
948
949 service_arg_out:
950         /*-------- DEBUG LOG --------*/
951         if (sslid_protomod.get_log_level != NULL &&
952             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
953                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,122,
954                     "out_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
955                     "handle_t srv_handle):return_value=%d", return_value);
956         }
957         /*------ DEBUG LOG END ------*/
958
959         return return_value;
960 }
961
962 /*!
963  * Parse l7vsadm options to sslid argument
964  * @param[out] sslid_arg sslid service argument struct
965  * @param[in]  argc      number of l7vsadm argument
966  * @param[in]  argv      l7vsadm argument list
967  * @retval 0  successfully parse argument
968  * @retval -1 some errors occur.
969  */
970 static int
971 parse(void* sslid_arg, int argc, char* argv[])
972 {
973         struct l7vs_sslid_service_arg* sslid_service_arg;
974         static struct option opt[] = {
975                 {"timeout",    required_argument, NULL, 'T'},
976                 {"maxlist",        required_argument, NULL, 'M'},
977                 {"reschedule",             no_argument,       NULL, 'R'},
978                 {"no-reschedule",          no_argument,       NULL, 'N'},
979                 {NULL,                     0,                 NULL, 0  }
980         };
981         int c;
982         unsigned long buffer;
983         int timeout_flag = 0;
984         int maxlist_flag = 0;
985         int reschedule_flag = 0;
986         int return_value = 0;
987
988         /*-------- DEBUG LOG --------*/
989         if (sslid_protomod.get_log_level != NULL &&
990             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
991                 int i;
992                 char argv_str[DEBUG_STR_LEN] = {0};
993                 char sslid_arg_str[DEBUG_STR_LEN] = {0};
994                 l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) sslid_arg);
995                 argv_str[0] = '\0';
996                 if (argv == NULL)
997                         snprintf(argv_str, DEBUG_STR_LEN, "NULL");
998                 else {
999                         for (i = 0; i < argc; i++) {
1000                                 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1001                         }
1002                         i = strnlen(argv_str, DEBUG_STR_LEN);
1003                         if (i > 1)
1004                                 argv_str[i - 2] = '\0';
1005                 }
1006                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,123,
1007                     "in_function: int parse(void* sslid_arg, int argc, char* argv[]):sslid_arg=&(%s), "
1008                     "argc=%d, %s", sslid_arg_str, argc, argv_str);
1009         }
1010         /*------ DEBUG LOG END ------*/
1011
1012         /* check null */
1013         if (sslid_arg == NULL) {
1014                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105, "Arg(sslid_arg) is NULL pointer.");
1015                 return_value = -1;
1016                 goto parse_out;
1017         }
1018         if (argv == NULL) {
1019                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,106, "Arg(argv) is NULL pointer.");
1020                 return_value = -1;
1021                 goto parse_out;
1022         }
1023
1024         sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
1025         optind = 0;
1026
1027         /* check all argument */
1028         while ((c = getopt_long(argc, argv, "T:M:RN", opt, NULL)) != -1) {
1029                 switch (c) {
1030                 /* --timeout / -T */
1031                 case 'T':
1032                         if (sscanf(optarg, "%lu", &buffer) == 0) {
1033                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
1034                                     "-T/--timeout option value '%s' is invalid.", optarg);
1035                                 return_value = -1;
1036                                 goto parse_out;
1037                         }
1038                         if (buffer > INT_MAX) {
1039                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
1040                                     "-T/--timeout option value '%s' is too large.", optarg);
1041                                 return_value = -1;
1042                                 goto parse_out;
1043                         }
1044                         else
1045                                 sslid_service_arg->timeout = buffer;
1046                         timeout_flag++;
1047                         break;
1048
1049                 /* --maxlist / -M */
1050                 case 'M':
1051                         if (sscanf(optarg, "%lu", &buffer) == 0) {
1052                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109,
1053                                     "-M/--maxlist option value '%s' is invalid.", optarg);
1054                                 return_value = -1;
1055                                 goto parse_out;
1056                         }
1057                         if (buffer > INT_MAX) {
1058                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110,
1059                                     "-M/--maxlist option value '%s' is too large.", optarg);
1060                                 return_value = -1;
1061                                 goto parse_out;
1062                         }
1063                         else
1064                                 sslid_service_arg->maxlist = buffer;
1065                         maxlist_flag++;
1066                         break;
1067
1068                 /* --reschedule / -R */
1069                 case 'R':
1070                         /* reschedule on */
1071                         sslid_service_arg->reschedule = 1;
1072                         reschedule_flag++;
1073                         break;
1074
1075                 /* --no-reschedule / -N */
1076                 case 'N':
1077                         /* reschedule off */
1078                         sslid_service_arg->reschedule = 0;
1079                         reschedule_flag++;
1080                         break;
1081
1082                 /* else error */
1083                 default:
1084                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111, "Option error.");
1085                         return_value = -1;
1086                         goto parse_out;
1087                 }
1088         }
1089
1090         /* when set both -R and -N at the same time */
1091         if (reschedule_flag > 1) {
1092                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,112,
1093                     "You should choose either reschdule or no-reschedule.");
1094                 return_value = -1;
1095                 goto parse_out;
1096         }
1097         /* same option */
1098         if (timeout_flag > 1) {
1099                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,113,
1100                     "Cannot set multiple option '--timeout/-T'.");
1101                 return_value = -1;
1102                 goto parse_out;
1103         }
1104         if (maxlist_flag > 1) {
1105                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
1106                     "Cannot set multiple option '--maxlist/-M'.");
1107                 return_value = -1;
1108                 goto parse_out;
1109         }
1110
1111         /* set default no reschedule */
1112         if (reschedule_flag == 0) {
1113                 sslid_service_arg->reschedule = 0;
1114         }
1115
1116         /* set default options */
1117         if (timeout_flag == 0) {
1118                 sslid_service_arg->timeout = 3600;
1119         }
1120         if (maxlist_flag == 0 || sslid_service_arg->maxlist == 0) {
1121                 sslid_service_arg->maxlist = 1024;
1122         }
1123
1124 parse_out:
1125         /*-------- DEBUG LOG --------*/
1126         if (sslid_protomod.get_log_level != NULL &&
1127             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1128                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,124,
1129                     "out_function: int parse(void* sslid_arg, int argc, char* argv[]):return_value=%d",
1130                     return_value);
1131         }
1132         /*------ DEBUG LOG END ------*/
1133
1134         return return_value;
1135 }
1136
1137 /*!
1138  * Search sslid service from sslid service list using service handle
1139  * @param[in] service_handle a unique service ID
1140  * @return sslid service struct when service was found. NULL when service was not found.
1141  */
1142 static struct l7vs_sslid_service*
1143 l7vs_protomod_sslid_search_service(handle_t service_handle)
1144 {
1145         /* sslid service list counter */
1146         int service_number = 0;
1147         struct l7vs_sslid_service* return_value = NULL;
1148
1149         /*-------- DEBUG LOG --------*/
1150         if (sslid_protomod.get_log_level != NULL &&
1151             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1152                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,125,
1153                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1154                     "service_handle=%d", service_handle);
1155         }
1156         /*------ DEBUG LOG END ------*/
1157
1158         /* check all sslid service list */
1159         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
1160                 /* found the service has same service handle */
1161                 if (sslid_service_list[service_number] != NULL && 
1162                     sslid_service_list[service_number]->service_handle == service_handle) {
1163                         return_value = sslid_service_list[service_number];
1164                         break;
1165                 }
1166         }
1167         
1168         /*-------- DEBUG LOG --------*/
1169         if (sslid_protomod.get_log_level != NULL &&
1170             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1171                 char ssl_str[DEBUG_STR_LEN] = {0};
1172                 l7vs_sslid_service_c_str(ssl_str, return_value);
1173                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,126,
1174                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1175                     "return_value=&(%s)", ssl_str);
1176         }
1177         /*------ DEBUG LOG END ------*/
1178
1179         return return_value;
1180 }
1181
1182 /*!
1183  * Create sslid service.
1184  * @param  void
1185  * @return sslid service struct when create a service. NULL when cannot create service.
1186  */
1187 static struct l7vs_sslid_service*
1188 l7vs_protomod_sslid_create_service()
1189 {
1190         int service_number = 0;
1191         struct l7vs_sslid_service* return_value = NULL;
1192
1193         /*-------- DEBUG LOG --------*/
1194         if (sslid_protomod.get_log_level != NULL &&
1195             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1196                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,127,
1197                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service()");
1198         }
1199         /*------ DEBUG LOG END ------*/
1200
1201         /* check all sslid service list */
1202         for (service_number = 0; service_number < SSLID_SERVICE_NUMBER - 1; ++service_number) {
1203                 /* if pointer that does not point NULL exists ... */
1204                 if (sslid_service_list[service_number] == NULL) {
1205                         /* create a service at empty pointer */
1206                         sslid_service_list[service_number] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1207
1208                         /*-------- DEBUG LOG --------*/
1209                         if (sslid_protomod.get_log_level != NULL &&
1210                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1211                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,32, "calloc: addr=%p, size=%ld",
1212                                     sslid_service_list[service_number], (unsigned long int) sizeof(struct l7vs_sslid_service));
1213                         }
1214                         /*------ DEBUG LOG END ------*/
1215
1216                         if (sslid_service_list[service_number] == NULL) {
1217                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,25, "Could not allocate memory.");
1218                                 goto create_service_out;
1219                         }
1220                         return_value = sslid_service_list[service_number];
1221                         goto create_service_out;
1222                 }
1223         }
1224         
1225         /* all service list is full */
1226         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115, "sslid service list is full.");
1227
1228 create_service_out:
1229         /*-------- DEBUG LOG --------*/
1230         if (sslid_protomod.get_log_level != NULL &&
1231             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1232                 char ssl_str[DEBUG_STR_LEN] = {0};
1233                 l7vs_sslid_service_c_str(ssl_str, return_value);
1234                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,128,
1235                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1236                     "return_value=&(%s)", ssl_str);
1237         }
1238         /*------ DEBUG LOG END ------*/
1239
1240         return return_value;
1241 }
1242
1243 /*!
1244  * Create temporary sslid service.
1245  * @param  void
1246  * @return sslid service struct when create a service. NULL when cannot create service.
1247  */
1248 static struct l7vs_sslid_service*
1249 l7vs_protomod_sslid_create_temp_service()
1250 {
1251         struct l7vs_sslid_service* return_value = NULL;
1252
1253         /*-------- DEBUG LOG --------*/
1254         if (sslid_protomod.get_log_level != NULL &&
1255             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1256                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,129,
1257                     "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_temp_service()");
1258         }
1259         /*------ DEBUG LOG END ------*/
1260
1261         /* if pointer that does not point NULL exists ... */
1262         if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] != NULL) {
1263                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116, "Temporary sslid service is being used by other process.");
1264                 goto create_temp_service_out;
1265         }
1266
1267         /* create temp service */
1268         sslid_service_list[SSLID_SERVICE_NUMBER - 1] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1269
1270         /*-------- DEBUG LOG --------*/
1271         if (sslid_protomod.get_log_level != NULL &&
1272             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1273                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,33, "calloc: addr=%p, size=%ld",
1274                     sslid_service_list[SSLID_SERVICE_NUMBER - 1], (unsigned long int) sizeof(struct l7vs_sslid_service));
1275         }
1276         /*------ DEBUG LOG END ------*/
1277
1278         if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] == NULL) {
1279                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,26, "Could not allocate memory");
1280                 goto create_temp_service_out;
1281         }
1282
1283         return_value = sslid_service_list[SSLID_SERVICE_NUMBER - 1];
1284
1285 create_temp_service_out:
1286         /*-------- DEBUG LOG --------*/
1287         if (sslid_protomod.get_log_level != NULL &&
1288             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1289                 char ssl_str[DEBUG_STR_LEN] = {0};
1290                 l7vs_sslid_service_c_str(ssl_str, return_value);
1291                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,130,
1292                     "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1293                     "return_value=&(%s)", ssl_str);
1294         }
1295         /*------ DEBUG LOG END ------*/
1296
1297         return return_value;
1298 }
1299
1300 /*!
1301  * Read replication area and set session data.
1302  * @param[in] sslid_service read this sslid service's session.
1303  * @return void
1304  */
1305 static void l7vs_protomod_sslid_read_replication_data(struct l7vs_sslid_service* sslid_service, struct l7vs_service* srv)
1306 {
1307         struct replication_header* head;
1308         struct replication_header* pick = NULL;
1309         unsigned int data_size = 0;
1310         unsigned int used = 0;
1311         void* data_addr = NULL;
1312         char exist = -1;
1313         int srv_num;
1314
1315         /*-------- DEBUG LOG --------*/
1316         if (sslid_protomod.get_log_level != NULL &&
1317             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1318                 char ssl_str[DEBUG_STR_LEN] = {0};
1319                 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1320                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,131,
1321                     "in_function: void l7vs_protomod_sslid_read_replication_data(struct "
1322                     "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1323         }
1324         /*------ DEBUG LOG END ------*/
1325
1326         /* check null */
1327         if (sslid_service == NULL) {
1328                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1329                 goto read_replication_data_out;
1330         }
1331         if (sslid_service->session == NULL) {
1332                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1333                 goto read_replication_data_out;
1334         }
1335         if (srv == NULL) {
1336                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1337                     "Service that has handle(%d) is not found.", sslid_service->service_handle);
1338                 goto read_replication_data_out;
1339         }
1340         if (srv->lsock == NULL) {
1341                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1342                     "Conn of service that has handle(%d) is NULL pointer.", sslid_service->service_handle);
1343                 goto read_replication_data_out;
1344         }
1345
1346         /* get replication area address */
1347         data_addr = sslid_protomod.replication_pay_memory(sslid_protomod.modname, &data_size);
1348         if (data_addr == NULL || data_size <= 0)
1349                 goto read_replication_data_out;
1350
1351         /* check replication area header */
1352         for (srv_num = 0; srv_num < SSLID_SERVICE_NUMBER; srv_num++) {
1353                 head = (struct replication_header*) data_addr + srv_num;
1354                 used += head->size;
1355
1356                 if (data_size * DATA_SIZE < sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used) {
1357                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Over replication area.");
1358                         goto read_replication_data_out;
1359                 }
1360
1361                 if (pick == NULL && head->size == 0)
1362                         pick = head;
1363                 if (exist >= 0 && pick != NULL)
1364                         break;
1365
1366                 /* match ip and port, this is pre-used session information */
1367                 if (memcmp(&head->sin_addr, &srv->lsock->addr.sin_addr, sizeof(struct in_addr)) == 0 &&
1368                     head->sin_port == srv->lsock->addr.sin_port) {
1369                         exist = srv_num;
1370                 }
1371         }
1372
1373         if (exist >= 0) {
1374                 head = (struct replication_header*) data_addr + exist;
1375
1376                 /* restore session information */
1377                 if (sslid_service->maxlist * sizeof(struct ssl_session) > head->size) {
1378                         // resize if maxlist set bigger than old
1379                         if (pick != NULL) {
1380                                 /* area size check */
1381                                 if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1382                                     used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1383                                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1384                                             "Replication area is full.");
1385                                         goto read_replication_data_out;
1386                                 }
1387                                 else {
1388                                         memcpy(sslid_service->session, (char*) data_addr + head->offset, head->size);
1389                                         memset(sslid_service->replication_addr, 0, head->size);
1390                                         sslid_service->replication_addr = (char*) data_addr +
1391                                             sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1392                                         pick->sin_addr = srv->lsock->addr.sin_addr;
1393                                         pick->sin_port = srv->lsock->addr.sin_port;
1394                                         pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1395                                         pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1396
1397                                         /*-------- DEBUG LOG --------*/
1398                                         if (sslid_protomod.get_log_level != NULL &&
1399                                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1400                                                 char head_str[DEBUG_STR_LEN];
1401                                                 replication_header_c_str(head_str, pick);
1402                                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1403                                                     "Write replication area: head=(%s)", head_str);
1404                                         }
1405                                         /*------ DEBUG LOG END ------*/
1406
1407                                         // you should garbage old session area...
1408                                 }
1409                         }
1410                         else {
1411                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1412                                     "Replication area is full.");
1413                                 goto read_replication_data_out;
1414                         }
1415                 }
1416                 else {
1417                         sslid_service->replication_addr = (char*) data_addr + head->offset;
1418                         memcpy(sslid_service->session, sslid_service->replication_addr,
1419                             sslid_service->maxlist * sizeof(struct ssl_session));
1420                         head->size = sslid_service->maxlist * sizeof(struct ssl_session);
1421
1422                         /*-------- DEBUG LOG --------*/
1423                         if (sslid_protomod.get_log_level != NULL &&
1424                             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1425                                 char head_str[DEBUG_STR_LEN];
1426                                 replication_header_c_str(head_str, head);
1427                                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1428                                     "Write replication area: head=(%s)", head_str);
1429                         }
1430                         /*------ DEBUG LOG END ------*/
1431                 }
1432         }
1433
1434         if (exist == -1) {
1435                 if (pick != NULL) {
1436                         /* area size check */
1437                         if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1438                             used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1439                                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1440                                     "Replication area is full.");
1441                                 goto read_replication_data_out;
1442                         }
1443                         else {
1444                                 /* initialize replication information */
1445                                 sslid_service->replication_addr = (char*) data_addr +
1446                                     sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1447                                 pick->sin_addr = srv->lsock->addr.sin_addr;
1448                                 pick->sin_port = srv->lsock->addr.sin_port;
1449                                 pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1450                                 pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1451
1452                                 /*-------- DEBUG LOG --------*/
1453                                 if (sslid_protomod.get_log_level != NULL &&
1454                                     LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1455                                         char head_str[DEBUG_STR_LEN];
1456                                         replication_header_c_str(head_str, pick);
1457                                         PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1458                                             "Write replication area: head=(%s)", head_str);
1459                                 }
1460                                 /*------ DEBUG LOG END ------*/
1461                         }
1462                 }
1463                 else {
1464                         PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1465                             "Replication area is full.");
1466                         goto read_replication_data_out;
1467                 }
1468         }
1469
1470 read_replication_data_out:
1471         /*-------- DEBUG LOG --------*/
1472         if (sslid_protomod.get_log_level != NULL &&
1473             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1474                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,132,
1475                     "out_function: l7vs_protomod_sslid_read_replication_data(struct "
1476                     "l7vs_sslid_service* sslid_service)");
1477         }
1478         /*------ DEBUG LOG END ------*/
1479 }
1480
1481 /*!
1482  * Write session data to replication area.
1483  * @param[in] sslid_service save this sslid service's session.
1484  * @return void
1485  */
1486 static void l7vs_protomod_sslid_write_replication_data(struct l7vs_sslid_service* sslid_service)
1487 {
1488         /*-------- DEBUG LOG --------*/
1489         if (sslid_protomod.get_log_level != NULL &&
1490             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1491                 char ssl_str[DEBUG_STR_LEN] = {0};
1492                 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1493                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,133,
1494                     "in_function: void l7vs_protomod_sslid_write_replication_data(struct "
1495                     "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1496         }
1497         /*------ DEBUG LOG END ------*/
1498
1499         /* check null */
1500         if (sslid_service == NULL) {
1501                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1502                 goto write_replication_data_out;
1503         }
1504         if (sslid_service->session == NULL) {
1505                 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1506                 goto write_replication_data_out;
1507         }
1508         /* no replicate setting */
1509         if (sslid_service->replication_addr == NULL) {
1510                 goto write_replication_data_out;
1511         }
1512
1513         /* copy session data */
1514         memcpy(sslid_service->replication_addr, sslid_service->session,
1515             sizeof(struct ssl_session) * sslid_service->maxlist);
1516
1517         /*-------- DEBUG LOG --------*/
1518         if (sslid_protomod.get_log_level != NULL &&
1519             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1520                 char session_str[DEBUG_STR_LEN];
1521                 ssl_session_c_str(session_str, (struct ssl_session*) sslid_service->replication_addr);
1522                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Write replication area: session=(%s)",
1523                     session_str);
1524         }
1525         /*------ DEBUG LOG END ------*/
1526
1527 write_replication_data_out:
1528         /*-------- DEBUG LOG --------*/
1529         if (sslid_protomod.get_log_level != NULL &&
1530             LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1531                 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,134,
1532                     "out_function: void l7vs_protomod_sslid_write_replication_data(struct "
1533                     "l7vs_sslid_service* sslid_service)");
1534         }
1535         /*------ DEBUG LOG END ------*/
1536 }
1537
1538 /*!
1539  * Serialize struct l7vs_sslid_service for debug log.
1540  * @param[out] buf   serialized string
1541  * @param[in]  sslid l7vs_sslid_service struct
1542  */
1543 static void l7vs_sslid_service_c_str(char* buf, struct l7vs_sslid_service* sslid) {
1544         if (sslid == NULL) {
1545                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1546         }
1547         else {
1548                 char session_str[DEBUG_STR_LEN] = {0};
1549                 ssl_session_c_str(session_str, sslid->session);
1550                 snprintf(buf, DEBUG_STR_LEN, "service_handle=%d, timeout=%d, maxlist=%d, "
1551                     "session=(%s), replication_addr=%p, reschedule=%d", sslid->service_handle,
1552                     sslid->timeout, sslid->maxlist, session_str, sslid->replication_addr,
1553                     sslid->reschedule);
1554         }
1555 }
1556
1557 /*!
1558  * Serialize struct l7vs_sslid_service_arg for debug log.
1559  * @param[out] buf       serialized string
1560  * @param[in]  sslid_arg l7vs_sslid_service_arg struct
1561  */
1562 void l7vs_sslid_service_arg_c_str(char* buf, struct l7vs_sslid_service_arg* sslid_arg) {
1563         if (sslid_arg == NULL) {
1564                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1565         }
1566         else {
1567                 snprintf(buf, DEBUG_STR_LEN, "timeout=%d, maxlist=%d, reschedule=%d",
1568                     sslid_arg->timeout, sslid_arg->maxlist, sslid_arg->reschedule);
1569         }
1570 }
1571
1572 /*!
1573  * Serialize struct ssl_session for debug log.
1574  * @param[out] buf     serialized string
1575  * @param[in]  session ssl_session struct
1576  */
1577 static void ssl_session_c_str(char* buf, struct ssl_session* session) {
1578         if (session == NULL) {
1579                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1580         }
1581         else {
1582                 char dest_str[DEBUG_STR_LEN] = {0};
1583                 char session_str[SSLID_LENGTH * 2 + 1];
1584                 l7vs_dest_c_str(dest_str, &session->dest);
1585                 id_c_str(session_str, session->id);
1586                 snprintf(buf, DEBUG_STR_LEN, "id=%s, dest=(%s), last_time=%d, valid=%d",
1587                     session_str, dest_str, (u_int) session->last_time, (int)session->valid);
1588         }
1589 }
1590
1591 /*!
1592  * Serialize struct replication_header for debug log.
1593  * @param[out] buf  serialized string
1594  * @param[in]  head replication_header struct
1595  */
1596 static void replication_header_c_str(char* buf, struct replication_header* head) {
1597         if (head == NULL) {
1598                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1599         }
1600         else {
1601                 snprintf(buf, DEBUG_STR_LEN, "sin_addr=(s_addr=%ld), sin_port=%d, size=%d, offset=%d",
1602                     (u_long) head->sin_addr.s_addr, head->sin_port, head->size, head->offset);
1603         }
1604 }
1605
1606 /*!
1607  * Convert SSL session ID (binary to hex)
1608  * @param[out] buf hex string
1609  * @param[in]  id  SSL session ID
1610  */
1611 static void id_c_str(char* buf, char* id) {
1612         int i;
1613         if (id == NULL) {
1614                 snprintf(buf, DEBUG_STR_LEN, "NULL");
1615         }
1616         else {
1617                 for (i = 0; i < SSLID_LENGTH; i++) {
1618                         snprintf(buf + i * 2, DEBUG_STR_LEN - i * 2, "%02X", (unsigned int)id[i]);
1619                 }
1620         }
1621 }