OSDN Git Service

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