2 * @file protomod_sslid.c
3 * @brief protocol module of HTTPS(SSL/TLS).
4 * @brief this module provide session persistence by SSL session ID.
6 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7 * Copyright (C) 2008 NTT COMWARE Corporation.
8 * Copyright (C) 2009 Shinya TAKEBAYASHI
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.
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.
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
25 **********************************************************************/
27 #define __STDC_LIMIT_MACROS
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"
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*,
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**);
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();
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*);
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*);
70 struct l7vs_sslid_service* sslid_service_list[SSLID_SERVICE_NUMBER];
72 static struct l7vs_protomod sslid_protomod = {
74 "sslid", /* modname */
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 */
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
103 extern "C" struct l7vs_protomod*
106 struct l7vs_protomod* return_value = NULL;
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);
114 /*------ DEBUG LOG END ------*/
117 if (handle == NULL) {
118 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,79, "Arg(handle) is NULL pointer.");
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;
127 return_value = &sslid_protomod;
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);
138 /*------ DEBUG LOG END ------*/
143 * Protocol module finalize function. free all sslid service list just in case.
150 /* sslid service list counter */
151 int service_number = 0;
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)");
158 /*------ DEBUG LOG END ------*/
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) {
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);
173 /*------ DEBUG LOG END ------*/
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);
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]);
187 /*------ DEBUG LOG END ------*/
189 free(sslid_service_list[service_number]);
190 sslid_service_list[service_number] = NULL;
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)");
199 /*------ DEBUG LOG END ------*/
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.
210 create(void* sslid_arg, handle_t service_handle)
212 struct l7vs_sslid_service* sslid_service;
213 struct l7vs_sslid_service_arg* sslid_service_arg;
214 int return_value = 0;
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);
225 /*------ DEBUG LOG END ------*/
228 if (sslid_arg == NULL) {
229 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,80, "Arg(sslid_arg) is NULL pointer.");
234 if (service_handle != TEMP_SERVICEHANDLE) {
235 /* search empty sslid service list and create sslid service */
236 sslid_service = l7vs_protomod_sslid_create_service();
239 /* create temporary sslid service */
240 sslid_service = l7vs_protomod_sslid_create_temp_service();
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)",
251 /*------ DEBUG LOG END ------*/
253 if (sslid_service == NULL) {
254 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,81, "Could not make sslid service.");
259 sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
261 /* set service handle */
262 sslid_service->service_handle = service_handle;
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;
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();
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);
283 /*------ DEBUG LOG END ------*/
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);
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",
304 /*------ DEBUG LOG END ------*/
310 * Create sslid service argument struct.
311 * @param[out] srv_arg service argument struct
312 * @return sslid service argument struct
315 create_sa(struct l7vs_service_arg* srv_arg)
317 struct l7vs_sslid_service_arg* sslid_service_arg;
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)",
328 /*------ DEBUG LOG END ------*/
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;
337 /* create sslid service argument struct */
338 sslid_service_arg = (struct l7vs_sslid_service_arg*) calloc(1, sizeof(struct l7vs_sslid_service_arg));
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));
346 /*------ DEBUG LOG END ------*/
348 if (sslid_service_arg == NULL) {
349 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,24, "Could not allocate memory.");
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);
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);
367 /*------ DEBUG LOG END ------*/
369 return (void*) sslid_service_arg;
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.
380 compare(handle_t srv_handle1, handle_t srv_handle2)
382 int return_value = 0;
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);
391 /*------ DEBUG LOG END ------*/
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",
400 /*------ DEBUG LOG END ------*/
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.
417 match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn,
418 char* request, size_t* len, struct l7vs_dest** dest, int* tcps)
420 struct l7vs_sslid_service* sslid_service;
423 int return_value = 0;
425 char id_str[DEBUG_STR_LEN] = {0};
426 struct l7vs_dest *tmpdest = NULL;
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);
439 l7vs_dest_c_str(dest_str, *dest);
442 strncpy(dest_str, "NULL", DEBUG_STR_LEN);
445 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
448 strncpy(len_str, "NULL", DEBUG_STR_LEN);
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);
456 /*------ DEBUG LOG END ------*/
460 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,83, "Arg(srv) is NULL pointer.");
462 goto match_cldata_out;
464 if (srv->pm == NULL) {
465 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,84, "Arg(srv->pm) is NULL pointer.");
467 goto match_cldata_out;
469 if (request == NULL) {
470 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,85, "Arg(request) is NULL pointer.");
472 goto match_cldata_out;
475 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,86, "Arg(len) is NULL pointer.");
477 goto match_cldata_out;
480 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,87, "Arg(dest) is NULL pointer.");
482 goto match_cldata_out;
485 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,88, "Arg(tcps) is NULL pointer.");
487 goto match_cldata_out;
490 /* search service that has such a service ID */
491 sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
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)",
501 /*------ DEBUG LOG END ------*/
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.");
506 goto match_cldata_out;
508 if (sslid_service->session == NULL) {
509 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,90,
510 "Service has NULL pointer session.");
512 goto match_cldata_out;
515 /* read replication data */
516 l7vs_protomod_sslid_read_replication_data(sslid_service, srv);
517 hash_rebuild_sessionlist(sslid_service);
519 /* initialize protocol module ... clear destination list */
520 ret = srv->pm->initialize(srv, conn, request, *len, dest);
522 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,91, "Could not initialize protomod.");
524 goto match_cldata_out;
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
534 request[5] == 0x01 && // Client Hello
535 request[43] == 0x20 // Session ID Length
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);
545 /*------ DEBUG LOG END ------*/
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);
551 if (searchret == 0) {
559 /* finalize, always set reschedule flag */
560 ret = srv->pm->finalize(srv, conn, request, *len, dest, sslid_service->reschedule);
562 PUT_LOG_INFO(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,11, "Could not finalize protomod. (Realserver decision failure)");
564 goto 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",
576 /*------ DEBUG LOG END ------*/
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.
591 analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn,
592 char* response, size_t* len)
594 struct l7vs_sslid_service* sslid_service;
596 int return_value = 0;
599 time_t now, oldest = 0;
600 char session_full = 1;
601 char id_str[DEBUG_STR_LEN] = {0};
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);
612 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
615 strncpy(len_str, "NULL", DEBUG_STR_LEN);
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);
622 /*------ DEBUG LOG END ------*/
626 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,93, "Arg(srv) is NULL pointer.");
628 goto analyze_rsdata_out;
631 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,94, "Arg(conn) is NULL pointer.");
633 goto analyze_rsdata_out;
635 if (conn->dest == NULL) {
636 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,95, "Arg(conn->dest) is NULL pointer.");
638 goto analyze_rsdata_out;
640 if (response == NULL) {
641 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,96, "Arg(response) is NULL pointer.");
643 goto analyze_rsdata_out;
646 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,97, "Arg(len) is NULL pointer.");
648 goto analyze_rsdata_out;
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.");
658 /*------ DEBUG LOG END ------*/
660 goto analyze_rsdata_out;
663 /* search service that has such a service ID */
664 sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
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)",
674 /*------ DEBUG LOG END ------*/
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.");
680 goto analyze_rsdata_out;
682 if (sslid_service->session == NULL) {
683 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,99,
684 "Service has NULL pointer session.");
686 goto analyze_rsdata_out;
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
696 response[5] == 0x02 && // Server Hello
697 response[43] == 0x20 // Session ID Length
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);
707 /*------ DEBUG LOG END ------*/
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);
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);
724 /*------ DEBUG LOG END ------*/
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.
736 destroy(handle_t srv_handle)
738 /* sslid service list counter */
739 int service_number = 0;
741 int return_value = 0;
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",
750 /*------ DEBUG LOG END ------*/
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) {
759 if (sslid_service_list[service_number]->session != NULL) {
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);
767 /*------ DEBUG LOG END ------*/
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);
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]);
781 /*------ DEBUG LOG END ------*/
783 free(sslid_service_list[service_number]);
784 sslid_service_list[service_number] = NULL;
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.");
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",
806 /*------ DEBUG LOG END ------*/
812 * Destroy sslid service argument
813 * @param[in] sslid_arg sslid service argument
817 destroy_sa(void** sslid_arg)
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);
827 strncpy(sslid_arg_str, "NULL", DEBUG_STR_LEN);
829 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,117,
830 "in_function: void destroy_sa(void** sslid_arg):sslid_arg=&(&(%s))",
833 /*------ DEBUG LOG END ------*/
836 if (sslid_arg == NULL) {
837 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,101, "Arg(sslid_arg) is NULL pointer.");
839 else if (*sslid_arg == NULL) {
840 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,102, "Arg(*sslid_arg) is NULL pointer.");
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",
849 /*------ DEBUG LOG END ------*/
852 free((struct l7vs_sslid_service_arg*) *sslid_arg);
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)");
862 /*------ DEBUG LOG END ------*/
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.
873 service_arg(struct l7vs_service_arg_multi* srv_arg_mt, handle_t srv_handle)
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;
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);
890 /*------ DEBUG LOG END ------*/
893 if (srv_arg_mt == NULL) {
894 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,103, "Arg(srv_arg_mt) is NULL pointer.");
896 goto service_arg_out;
899 /* search service that has such a service ID */
900 sslid_service = l7vs_protomod_sslid_search_service(srv_handle);
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)",
910 /*------ DEBUG LOG END ------*/
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.");
915 goto service_arg_out;
918 /* initialize argument strings */
919 memset(sslid_argument, 0, SERVICE_ARG_MAXSIZE);
921 /* set sslid args to service argument struct */
922 srv_arg_mt->srv_arg.reschedule = sslid_service->reschedule;
924 /* create long argument (l7vsadm option -l) */
925 strncpy(srv_arg_mt->srv_arg.protomod_key_string, sslid_argument, 256);
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);
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;
937 memcpy(srv_arg_mt->protomod_arg, &s_sarg, sizeof(struct l7vs_sslid_service_arg));
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);
947 /*------ DEBUG LOG END ------*/
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);
957 /*------ DEBUG LOG END ------*/
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.
971 parse(void* sslid_arg, int argc, char* argv[])
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'},
982 unsigned long buffer;
983 int timeout_flag = 0;
984 int maxlist_flag = 0;
985 int reschedule_flag = 0;
986 int return_value = 0;
988 /*-------- DEBUG LOG --------*/
989 if (sslid_protomod.get_log_level != NULL &&
990 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
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);
997 snprintf(argv_str, DEBUG_STR_LEN, "NULL");
999 for (i = 0; i < argc; i++) {
1000 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1002 i = strnlen(argv_str, DEBUG_STR_LEN);
1004 argv_str[i - 2] = '\0';
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);
1010 /*------ DEBUG LOG END ------*/
1013 if (sslid_arg == NULL) {
1014 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105, "Arg(sslid_arg) is NULL pointer.");
1019 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,106, "Arg(argv) is NULL pointer.");
1024 sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
1027 /* check all argument */
1028 while ((c = getopt_long(argc, argv, "T:M:RN", opt, NULL)) != -1) {
1030 /* --timeout / -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);
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);
1045 sslid_service_arg->timeout = buffer;
1049 /* --maxlist / -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);
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);
1064 sslid_service_arg->maxlist = buffer;
1068 /* --reschedule / -R */
1071 sslid_service_arg->reschedule = 1;
1075 /* --no-reschedule / -N */
1077 /* reschedule off */
1078 sslid_service_arg->reschedule = 0;
1084 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111, "Option error.");
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.");
1098 if (timeout_flag > 1) {
1099 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,113,
1100 "Cannot set multiple option '--timeout/-T'.");
1104 if (maxlist_flag > 1) {
1105 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
1106 "Cannot set multiple option '--maxlist/-M'.");
1111 /* set default no reschedule */
1112 if (reschedule_flag == 0) {
1113 sslid_service_arg->reschedule = 0;
1116 /* set default options */
1117 if (timeout_flag == 0) {
1118 sslid_service_arg->timeout = 3600;
1120 if (maxlist_flag == 0 || sslid_service_arg->maxlist == 0) {
1121 sslid_service_arg->maxlist = 1024;
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",
1132 /*------ DEBUG LOG END ------*/
1134 return return_value;
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.
1142 static struct l7vs_sslid_service*
1143 l7vs_protomod_sslid_search_service(handle_t service_handle)
1145 /* sslid service list counter */
1146 int service_number = 0;
1147 struct l7vs_sslid_service* return_value = NULL;
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);
1156 /*------ DEBUG LOG END ------*/
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];
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);
1177 /*------ DEBUG LOG END ------*/
1179 return return_value;
1183 * Create sslid service.
1185 * @return sslid service struct when create a service. NULL when cannot create service.
1187 static struct l7vs_sslid_service*
1188 l7vs_protomod_sslid_create_service()
1190 int service_number = 0;
1191 struct l7vs_sslid_service* return_value = NULL;
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()");
1199 /*------ DEBUG LOG END ------*/
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));
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));
1214 /*------ DEBUG LOG END ------*/
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;
1220 return_value = sslid_service_list[service_number];
1221 goto create_service_out;
1225 /* all service list is full */
1226 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115, "sslid service list is full.");
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);
1238 /*------ DEBUG LOG END ------*/
1240 return return_value;
1244 * Create temporary sslid service.
1246 * @return sslid service struct when create a service. NULL when cannot create service.
1248 static struct l7vs_sslid_service*
1249 l7vs_protomod_sslid_create_temp_service()
1251 struct l7vs_sslid_service* return_value = NULL;
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()");
1259 /*------ DEBUG LOG END ------*/
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;
1267 /* create temp service */
1268 sslid_service_list[SSLID_SERVICE_NUMBER - 1] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
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));
1276 /*------ DEBUG LOG END ------*/
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;
1283 return_value = sslid_service_list[SSLID_SERVICE_NUMBER - 1];
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);
1295 /*------ DEBUG LOG END ------*/
1297 return return_value;
1301 * Read replication area and set session data.
1302 * @param[in] sslid_service read this sslid service's session.
1305 static void l7vs_protomod_sslid_read_replication_data(struct l7vs_sslid_service* sslid_service, struct l7vs_service* srv)
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;
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);
1324 /*------ DEBUG LOG END ------*/
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;
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;
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;
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;
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;
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;
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;
1361 if (pick == NULL && head->size == 0)
1363 if (exist >= 0 && pick != NULL)
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) {
1374 head = (struct replication_header*) data_addr + exist;
1376 /* restore session information */
1377 if (sslid_service->maxlist * sizeof(struct ssl_session) > head->size) {
1378 // resize if maxlist set bigger than old
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;
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;
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);
1405 /*------ DEBUG LOG END ------*/
1407 // you should garbage old session area...
1411 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1412 "Replication area is full.");
1413 goto read_replication_data_out;
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);
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);
1430 /*------ DEBUG LOG END ------*/
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;
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;
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);
1460 /*------ DEBUG LOG END ------*/
1464 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1465 "Replication area is full.");
1466 goto read_replication_data_out;
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)");
1478 /*------ DEBUG LOG END ------*/
1482 * Write session data to replication area.
1483 * @param[in] sslid_service save this sslid service's session.
1486 static void l7vs_protomod_sslid_write_replication_data(struct l7vs_sslid_service* sslid_service)
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);
1497 /*------ DEBUG LOG END ------*/
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;
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;
1508 /* no replicate setting */
1509 if (sslid_service->replication_addr == NULL) {
1510 goto write_replication_data_out;
1513 /* copy session data */
1514 memcpy(sslid_service->replication_addr, sslid_service->session,
1515 sizeof(struct ssl_session) * sslid_service->maxlist);
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)",
1525 /*------ DEBUG LOG END ------*/
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)");
1535 /*------ DEBUG LOG END ------*/
1539 * Serialize struct l7vs_sslid_service for debug log.
1540 * @param[out] buf serialized string
1541 * @param[in] sslid l7vs_sslid_service struct
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");
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,
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
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");
1567 snprintf(buf, DEBUG_STR_LEN, "timeout=%d, maxlist=%d, reschedule=%d",
1568 sslid_arg->timeout, sslid_arg->maxlist, sslid_arg->reschedule);
1573 * Serialize struct ssl_session for debug log.
1574 * @param[out] buf serialized string
1575 * @param[in] session ssl_session struct
1577 static void ssl_session_c_str(char* buf, struct ssl_session* session) {
1578 if (session == NULL) {
1579 snprintf(buf, DEBUG_STR_LEN, "NULL");
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);
1592 * Serialize struct replication_header for debug log.
1593 * @param[out] buf serialized string
1594 * @param[in] head replication_header struct
1596 static void replication_header_c_str(char* buf, struct replication_header* head) {
1598 snprintf(buf, DEBUG_STR_LEN, "NULL");
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);
1607 * Convert SSL session ID (binary to hex)
1608 * @param[out] buf hex string
1609 * @param[in] id SSL session ID
1611 static void id_c_str(char* buf, char* id) {
1614 snprintf(buf, DEBUG_STR_LEN, "NULL");
1617 for (i = 0; i < SSLID_LENGTH; i++) {
1618 snprintf(buf + i * 2, DEBUG_STR_LEN - i * 2, "%02X", (unsigned int)id[i]);