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 if (sslid_service->replication_addr) {
517 l7vs_protomod_sslid_read_replication_data(sslid_service, srv);
518 hash_rebuild_sessionlist(sslid_service);
521 /* initialize protocol module ... clear destination list */
522 ret = srv->pm->initialize(srv, conn, request, *len, dest);
524 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,91, "Could not initialize protomod.");
526 goto match_cldata_out;
533 (request[1] == 0x03 && request[2] == 0x00 && request[9] == 0x03 && request [10] == 0x00) || // SSL v3
534 (request[1] == 0x03 && request[2] == 0x01 && request[9] == 0x03 && request [10] == 0x01) // TLS v1
536 request[5] == 0x01 && // Client Hello
537 request[43] == 0x20 // Session ID Length
539 /*-------- DEBUG LOG --------*/
540 if (sslid_protomod.get_log_level != NULL &&
541 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
542 char id_str[DEBUG_STR_LEN] = {0};
543 id_c_str(id_str, &request[44]);
544 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105,
545 "Client Hello/SessionID=%s", id_str);
547 /*------ DEBUG LOG END ------*/
549 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
550 id_c_str(id_str, &request[44]);
551 searchret = hash_search(id_str, &tmpdest);
553 if (searchret == 0) {
561 /* finalize, always set reschedule flag */
562 ret = srv->pm->finalize(srv, conn, request, *len, dest, sslid_service->reschedule);
564 PUT_LOG_INFO(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,11, "Could not finalize protomod. (Realserver decision failure)");
566 goto match_cldata_out;
570 /*-------- DEBUG LOG --------*/
571 if (sslid_protomod.get_log_level != NULL &&
572 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
573 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
574 "out_function: int match_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
575 "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):return_value=%d",
578 /*------ DEBUG LOG END ------*/
584 * Check and modify response packet.
585 * @param[in] srv service struct include service handle, protocol module and schedule module.
586 * @param[in] conn connection data.
587 * @param[in] response packet data from real server
588 * @param[in] len length of packet data. it will be lengthened.
589 * @retval 0 successfully check packet data.
590 * @retval -1 some errors occur.
593 analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn,
594 char* response, size_t* len)
596 struct l7vs_sslid_service* sslid_service;
598 int return_value = 0;
601 time_t now, oldest = 0;
602 char session_full = 1;
603 char id_str[DEBUG_STR_LEN] = {0};
605 /*-------- DEBUG LOG --------*/
606 if (sslid_protomod.get_log_level != NULL &&
607 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
608 char srv_str[DEBUG_STR_LEN] = {0};
609 char conn_str[DEBUG_STR_LEN] = {0};
610 char len_str[DEBUG_STR_LEN] = {0};
611 l7vs_service_c_str(srv_str, srv);
612 l7vs_conn_c_str(conn_str, conn);
614 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
617 strncpy(len_str, "NULL", DEBUG_STR_LEN);
619 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
620 "in_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
621 "char* response, size_t* len):srv=&(%s), conn=&(%s), response=\"%s\", len=&(%s)",
622 srv_str, conn_str, response, len_str);
624 /*------ DEBUG LOG END ------*/
628 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,93, "Arg(srv) is NULL pointer.");
630 goto analyze_rsdata_out;
633 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,94, "Arg(conn) is NULL pointer.");
635 goto analyze_rsdata_out;
637 if (conn->dest == NULL) {
638 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,95, "Arg(conn->dest) is NULL pointer.");
640 goto analyze_rsdata_out;
642 if (response == NULL) {
643 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,96, "Arg(response) is NULL pointer.");
645 goto analyze_rsdata_out;
648 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,97, "Arg(len) is NULL pointer.");
650 goto analyze_rsdata_out;
653 /* sorry flag check */
654 if (conn->sorry_conn_flag == 1) {
655 /*-------- DEBUG LOG --------*/
656 if (sslid_protomod.get_log_level != NULL &&
657 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
658 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109, "Response from sorry server.");
660 /*------ DEBUG LOG END ------*/
662 goto analyze_rsdata_out;
665 /* search service that has such a service ID */
666 sslid_service = l7vs_protomod_sslid_search_service(srv->handle);
668 /*-------- DEBUG LOG --------*/
669 if (sslid_protomod.get_log_level != NULL &&
670 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
671 char sslid_str[DEBUG_STR_LEN] = {0};
672 l7vs_sslid_service_c_str(sslid_str, sslid_service);
673 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110, "pointer assign: sslid_service=&(%s)",
676 /*------ DEBUG LOG END ------*/
678 if (sslid_service == NULL) {
679 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,98,
680 "Could not find such service handle's sslid service.");
682 goto analyze_rsdata_out;
684 if (sslid_service->session == NULL) {
685 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,99,
686 "Service has NULL pointer session.");
688 goto analyze_rsdata_out;
695 (response[1] == 0x03 && response[2] == 0x00 && response[9] == 0x03 && response [10] == 0x00) || // SSL v3
696 (response[1] == 0x03 && response[2] == 0x01 && response[9] == 0x03 && response [10] == 0x01) // TLS v1
698 response[5] == 0x02 && // Server Hello
699 response[43] == 0x20 // Session ID Length
701 /*-------- DEBUG LOG --------*/
702 if (sslid_protomod.get_log_level != NULL &&
703 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
704 char id_str[DEBUG_STR_LEN] = {0};
705 id_c_str(id_str, &response[44]);
706 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111,
707 "Server Hello/SessionID=%s", id_str);
709 /*------ DEBUG LOG END ------*/
711 hash_setPointer(sslid_service->hash_map, sslid_service->hash_list, sslid_service->maxlist);
712 id_c_str(id_str, &response[44]);
713 hash_add(id_str, *conn->dest);
714 if (sslid_service->replication_addr) {
715 hash_construct_sessionlist(sslid_service);
716 l7vs_protomod_sslid_write_replication_data(sslid_service);
721 /*-------- DEBUG LOG --------*/
722 if (sslid_protomod.get_log_level != NULL &&
723 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
724 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
725 "out_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
726 "char* response, size_t* len):return_value=%d", return_value);
728 /*------ DEBUG LOG END ------*/
734 * Destroy sslid service
735 * @param[in] srv_handle a unique service ID
736 * @retval 0 successfully check packet data.
737 * @retval -1 some errors occur.
740 destroy(handle_t srv_handle)
742 /* sslid service list counter */
743 int service_number = 0;
745 int return_value = 0;
747 /*-------- DEBUG LOG --------*/
748 if (sslid_protomod.get_log_level != NULL &&
749 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
750 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115,
751 "in_function: int destroy(handle_t srv_handle):srv_handle=%u",
754 /*------ DEBUG LOG END ------*/
756 /* check all sslid service list */
757 for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
758 /* found sslid service that has srv_handle */
759 if (sslid_service_list[service_number] != NULL &&
760 sslid_service_list[service_number]->service_handle == srv_handle) {
763 if (sslid_service_list[service_number]->session != NULL) {
765 /*-------- DEBUG LOG --------*/
766 if (sslid_protomod.get_log_level != NULL &&
767 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
768 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,29, "free: %p",
769 sslid_service_list[service_number]->session);
771 /*------ DEBUG LOG END ------*/
773 free(sslid_service_list[service_number]->session);
774 sslid_service_list[service_number]->session = NULL;
775 hash_setPointer(sslid_service_list[service_number]->hash_map, sslid_service_list[service_number]->hash_list, sslid_service_list[service_number]->maxlist);
779 /*-------- DEBUG LOG --------*/
780 if (sslid_protomod.get_log_level != NULL &&
781 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
782 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,30, "free: %p",
783 sslid_service_list[service_number]);
785 /*------ DEBUG LOG END ------*/
787 free(sslid_service_list[service_number]);
788 sslid_service_list[service_number] = NULL;
795 /* sslid service was not found */
796 if (free_flag == 0) {
797 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,100, "Could not find such service handle's sslid service.");
803 /*-------- DEBUG LOG --------*/
804 if (sslid_protomod.get_log_level != NULL &&
805 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
806 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116,
807 "out_function: int destroy(handle_t srv_handle):return_value=%d",
810 /*------ DEBUG LOG END ------*/
816 * Destroy sslid service argument
817 * @param[in] sslid_arg sslid service argument
821 destroy_sa(void** sslid_arg)
823 /*-------- DEBUG LOG --------*/
824 if (sslid_protomod.get_log_level != NULL &&
825 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
826 char sslid_arg_str[DEBUG_STR_LEN] = {0};
827 if (sslid_arg != NULL) {
828 l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) *sslid_arg);
831 strncpy(sslid_arg_str, "NULL", DEBUG_STR_LEN);
833 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,117,
834 "in_function: void destroy_sa(void** sslid_arg):sslid_arg=&(&(%s))",
837 /*------ DEBUG LOG END ------*/
840 if (sslid_arg == NULL) {
841 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,101, "Arg(sslid_arg) is NULL pointer.");
843 else if (*sslid_arg == NULL) {
844 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,102, "Arg(*sslid_arg) is NULL pointer.");
847 /*-------- DEBUG LOG --------*/
848 if (sslid_protomod.get_log_level != NULL &&
849 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
850 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,31, "free: %p",
853 /*------ DEBUG LOG END ------*/
856 free((struct l7vs_sslid_service_arg*) *sslid_arg);
860 /*-------- DEBUG LOG --------*/
861 if (sslid_protomod.get_log_level != NULL &&
862 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
863 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,118,
864 "out_function: void destroy_sa(void** sslid_arg)");
866 /*------ DEBUG LOG END ------*/
870 * Create strings for service list of l7vsadm
871 * @param[out] srv_arg_mt service argument struct
872 * @param[in] srv_handle a unique service ID
873 * @retval 0 successfully create strings
874 * @retval -1 some errors occur.
877 service_arg(struct l7vs_service_arg_multi* srv_arg_mt, handle_t srv_handle)
879 struct l7vs_sslid_service* sslid_service;
880 struct l7vs_sslid_service_arg s_sarg;
881 char sslid_argument[SERVICE_ARG_MAXSIZE];
882 int return_value = 0;
884 /*-------- DEBUG LOG --------*/
885 if (sslid_protomod.get_log_level != NULL &&
886 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
887 char srv_arg_mt_str[DEBUG_STR_LEN] = {0};
888 l7vs_service_arg_multi_c_str(srv_arg_mt_str, srv_arg_mt);
889 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,119,
890 "in_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
891 "handle_t srv_handle):srv_arg_mt=&(%s), srv_handle=%u",
892 srv_arg_mt_str, srv_handle);
894 /*------ DEBUG LOG END ------*/
897 if (srv_arg_mt == NULL) {
898 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,103, "Arg(srv_arg_mt) is NULL pointer.");
900 goto service_arg_out;
903 /* search service that has such a service ID */
904 sslid_service = l7vs_protomod_sslid_search_service(srv_handle);
906 /*-------- DEBUG LOG --------*/
907 if (sslid_protomod.get_log_level != NULL &&
908 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
909 char sslid_str[DEBUG_STR_LEN] = {0};
910 l7vs_sslid_service_c_str(sslid_str, sslid_service);
911 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,120, "pointer assign: sslid_service=&(%s)",
914 /*------ DEBUG LOG END ------*/
916 if (sslid_service == NULL) {
917 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,104, "Could not find such service handle's sslid service.");
919 goto service_arg_out;
922 /* initialize argument strings */
923 memset(sslid_argument, 0, SERVICE_ARG_MAXSIZE);
925 /* set sslid args to service argument struct */
926 srv_arg_mt->srv_arg.reschedule = sslid_service->reschedule;
928 /* create long argument (l7vsadm option -l) */
929 strncpy(srv_arg_mt->srv_arg.protomod_key_string, sslid_argument, 256);
931 /* create verbose argument (l7vsadm option -V) */
932 snprintf(sslid_argument + strlen(sslid_argument), SERVICE_ARG_MAXSIZE - strlen(sslid_argument),
933 "--timeout %d --maxlist %d", sslid_service->timeout, sslid_service->maxlist);
934 strncpy(srv_arg_mt->srv_arg.protomod_opt_string, sslid_argument, 512);
936 /* set option value */
937 s_sarg.timeout = sslid_service->timeout;
938 s_sarg.maxlist = sslid_service->maxlist;
939 s_sarg.reschedule = sslid_service->reschedule;
941 memcpy(srv_arg_mt->protomod_arg, &s_sarg, sizeof(struct l7vs_sslid_service_arg));
943 /*-------- DEBUG LOG --------*/
944 if (sslid_protomod.get_log_level != NULL &&
945 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
946 char sslid_arg_str[DEBUG_STR_LEN] = {0};
947 l7vs_sslid_service_arg_c_str(sslid_arg_str, &s_sarg);
948 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,121,
949 "pointer assign: srv_arg_mt->protomod_arg=&(%s)", sslid_arg_str);
951 /*------ DEBUG LOG END ------*/
954 /*-------- DEBUG LOG --------*/
955 if (sslid_protomod.get_log_level != NULL &&
956 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
957 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,122,
958 "out_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
959 "handle_t srv_handle):return_value=%d", return_value);
961 /*------ DEBUG LOG END ------*/
967 * Parse l7vsadm options to sslid argument
968 * @param[out] sslid_arg sslid service argument struct
969 * @param[in] argc number of l7vsadm argument
970 * @param[in] argv l7vsadm argument list
971 * @retval 0 successfully parse argument
972 * @retval -1 some errors occur.
975 parse(void* sslid_arg, int argc, char* argv[])
977 struct l7vs_sslid_service_arg* sslid_service_arg;
978 static struct option opt[] = {
979 {"timeout", required_argument, NULL, 'T'},
980 {"maxlist", required_argument, NULL, 'M'},
981 {"reschedule", no_argument, NULL, 'R'},
982 {"no-reschedule", no_argument, NULL, 'N'},
986 unsigned long buffer;
987 int timeout_flag = 0;
988 int maxlist_flag = 0;
989 int reschedule_flag = 0;
990 int return_value = 0;
992 /*-------- DEBUG LOG --------*/
993 if (sslid_protomod.get_log_level != NULL &&
994 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
996 char argv_str[DEBUG_STR_LEN] = {0};
997 char sslid_arg_str[DEBUG_STR_LEN] = {0};
998 l7vs_sslid_service_arg_c_str(sslid_arg_str, (struct l7vs_sslid_service_arg*) sslid_arg);
1001 snprintf(argv_str, DEBUG_STR_LEN, "NULL");
1003 for (i = 0; i < argc; i++) {
1004 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1006 i = strnlen(argv_str, DEBUG_STR_LEN);
1008 argv_str[i - 2] = '\0';
1010 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,123,
1011 "in_function: int parse(void* sslid_arg, int argc, char* argv[]):sslid_arg=&(%s), "
1012 "argc=%d, %s", sslid_arg_str, argc, argv_str);
1014 /*------ DEBUG LOG END ------*/
1017 if (sslid_arg == NULL) {
1018 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,105, "Arg(sslid_arg) is NULL pointer.");
1023 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,106, "Arg(argv) is NULL pointer.");
1028 sslid_service_arg = (struct l7vs_sslid_service_arg*) sslid_arg;
1031 /* check all argument */
1032 while ((c = getopt_long(argc, argv, "T:M:RN", opt, NULL)) != -1) {
1034 /* --timeout / -T */
1036 if (sscanf(optarg, "%lu", &buffer) == 0) {
1037 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,107,
1038 "-T/--timeout option value '%s' is invalid.", optarg);
1042 if (buffer > INT_MAX) {
1043 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,108,
1044 "-T/--timeout option value '%s' is too large.", optarg);
1049 sslid_service_arg->timeout = buffer;
1053 /* --maxlist / -M */
1055 if (sscanf(optarg, "%lu", &buffer) == 0) {
1056 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,109,
1057 "-M/--maxlist option value '%s' is invalid.", optarg);
1061 if (buffer > INT_MAX) {
1062 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,110,
1063 "-M/--maxlist option value '%s' is too large.", optarg);
1068 sslid_service_arg->maxlist = buffer;
1072 /* --reschedule / -R */
1075 sslid_service_arg->reschedule = 1;
1079 /* --no-reschedule / -N */
1081 /* reschedule off */
1082 sslid_service_arg->reschedule = 0;
1088 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,111, "Option error.");
1094 /* when set both -R and -N at the same time */
1095 if (reschedule_flag > 1) {
1096 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,112,
1097 "You should choose either reschdule or no-reschedule.");
1102 if (timeout_flag > 1) {
1103 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,113,
1104 "Cannot set multiple option '--timeout/-T'.");
1108 if (maxlist_flag > 1) {
1109 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,114,
1110 "Cannot set multiple option '--maxlist/-M'.");
1115 /* set default no reschedule */
1116 if (reschedule_flag == 0) {
1117 sslid_service_arg->reschedule = 0;
1120 /* set default options */
1121 if (timeout_flag == 0) {
1122 sslid_service_arg->timeout = 3600;
1124 if (maxlist_flag == 0 || sslid_service_arg->maxlist == 0) {
1125 sslid_service_arg->maxlist = 1024;
1129 /*-------- DEBUG LOG --------*/
1130 if (sslid_protomod.get_log_level != NULL &&
1131 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1132 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,124,
1133 "out_function: int parse(void* sslid_arg, int argc, char* argv[]):return_value=%d",
1136 /*------ DEBUG LOG END ------*/
1138 return return_value;
1142 * Search sslid service from sslid service list using service handle
1143 * @param[in] service_handle a unique service ID
1144 * @return sslid service struct when service was found. NULL when service was not found.
1146 static struct l7vs_sslid_service*
1147 l7vs_protomod_sslid_search_service(handle_t service_handle)
1149 /* sslid service list counter */
1150 int service_number = 0;
1151 struct l7vs_sslid_service* return_value = NULL;
1153 /*-------- DEBUG LOG --------*/
1154 if (sslid_protomod.get_log_level != NULL &&
1155 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1156 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,125,
1157 "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1158 "service_handle=%d", service_handle);
1160 /*------ DEBUG LOG END ------*/
1162 /* check all sslid service list */
1163 for (service_number = 0; service_number < SSLID_SERVICE_NUMBER; ++service_number) {
1164 /* found the service has same service handle */
1165 if (sslid_service_list[service_number] != NULL &&
1166 sslid_service_list[service_number]->service_handle == service_handle) {
1167 return_value = sslid_service_list[service_number];
1172 /*-------- DEBUG LOG --------*/
1173 if (sslid_protomod.get_log_level != NULL &&
1174 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1175 char ssl_str[DEBUG_STR_LEN] = {0};
1176 l7vs_sslid_service_c_str(ssl_str, return_value);
1177 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,126,
1178 "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_search_service(handle_t service_handle):"
1179 "return_value=&(%s)", ssl_str);
1181 /*------ DEBUG LOG END ------*/
1183 return return_value;
1187 * Create sslid service.
1189 * @return sslid service struct when create a service. NULL when cannot create service.
1191 static struct l7vs_sslid_service*
1192 l7vs_protomod_sslid_create_service()
1194 int service_number = 0;
1195 struct l7vs_sslid_service* return_value = NULL;
1197 /*-------- DEBUG LOG --------*/
1198 if (sslid_protomod.get_log_level != NULL &&
1199 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1200 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,127,
1201 "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service()");
1203 /*------ DEBUG LOG END ------*/
1205 /* check all sslid service list */
1206 for (service_number = 0; service_number < SSLID_SERVICE_NUMBER - 1; ++service_number) {
1207 /* if pointer that does not point NULL exists ... */
1208 if (sslid_service_list[service_number] == NULL) {
1209 /* create a service at empty pointer */
1210 sslid_service_list[service_number] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1212 /*-------- DEBUG LOG --------*/
1213 if (sslid_protomod.get_log_level != NULL &&
1214 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1215 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,32, "calloc: addr=%p, size=%ld",
1216 sslid_service_list[service_number], (unsigned long int) sizeof(struct l7vs_sslid_service));
1218 /*------ DEBUG LOG END ------*/
1220 if (sslid_service_list[service_number] == NULL) {
1221 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,25, "Could not allocate memory.");
1222 goto create_service_out;
1224 return_value = sslid_service_list[service_number];
1225 goto create_service_out;
1229 /* all service list is full */
1230 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,115, "sslid service list is full.");
1233 /*-------- DEBUG LOG --------*/
1234 if (sslid_protomod.get_log_level != NULL &&
1235 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1236 char ssl_str[DEBUG_STR_LEN] = {0};
1237 l7vs_sslid_service_c_str(ssl_str, return_value);
1238 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,128,
1239 "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1240 "return_value=&(%s)", ssl_str);
1242 /*------ DEBUG LOG END ------*/
1244 return return_value;
1248 * Create temporary sslid service.
1250 * @return sslid service struct when create a service. NULL when cannot create service.
1252 static struct l7vs_sslid_service*
1253 l7vs_protomod_sslid_create_temp_service()
1255 struct l7vs_sslid_service* return_value = NULL;
1257 /*-------- DEBUG LOG --------*/
1258 if (sslid_protomod.get_log_level != NULL &&
1259 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1260 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,129,
1261 "in_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_temp_service()");
1263 /*------ DEBUG LOG END ------*/
1265 /* if pointer that does not point NULL exists ... */
1266 if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] != NULL) {
1267 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,116, "Temporary sslid service is being used by other process.");
1268 goto create_temp_service_out;
1271 /* create temp service */
1272 sslid_service_list[SSLID_SERVICE_NUMBER - 1] = (struct l7vs_sslid_service*) calloc(1, sizeof(struct l7vs_sslid_service));
1274 /*-------- DEBUG LOG --------*/
1275 if (sslid_protomod.get_log_level != NULL &&
1276 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1277 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,33, "calloc: addr=%p, size=%ld",
1278 sslid_service_list[SSLID_SERVICE_NUMBER - 1], (unsigned long int) sizeof(struct l7vs_sslid_service));
1280 /*------ DEBUG LOG END ------*/
1282 if (sslid_service_list[SSLID_SERVICE_NUMBER - 1] == NULL) {
1283 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,26, "Could not allocate memory");
1284 goto create_temp_service_out;
1287 return_value = sslid_service_list[SSLID_SERVICE_NUMBER - 1];
1289 create_temp_service_out:
1290 /*-------- DEBUG LOG --------*/
1291 if (sslid_protomod.get_log_level != NULL &&
1292 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1293 char ssl_str[DEBUG_STR_LEN] = {0};
1294 l7vs_sslid_service_c_str(ssl_str, return_value);
1295 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,130,
1296 "out_function: struct l7vs_sslid_service* l7vs_protomod_sslid_create_service():"
1297 "return_value=&(%s)", ssl_str);
1299 /*------ DEBUG LOG END ------*/
1301 return return_value;
1305 * Read replication area and set session data.
1306 * @param[in] sslid_service read this sslid service's session.
1309 static void l7vs_protomod_sslid_read_replication_data(struct l7vs_sslid_service* sslid_service, struct l7vs_service* srv)
1311 struct replication_header* head;
1312 struct replication_header* pick = NULL;
1313 unsigned int data_size = 0;
1314 unsigned int used = 0;
1315 void* data_addr = NULL;
1319 /*-------- DEBUG LOG --------*/
1320 if (sslid_protomod.get_log_level != NULL &&
1321 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1322 char ssl_str[DEBUG_STR_LEN] = {0};
1323 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1324 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,131,
1325 "in_function: void l7vs_protomod_sslid_read_replication_data(struct "
1326 "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1328 /*------ DEBUG LOG END ------*/
1331 if (sslid_service == NULL) {
1332 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1333 goto read_replication_data_out;
1335 if (sslid_service->session == NULL) {
1336 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1337 goto read_replication_data_out;
1340 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1341 "Service that has handle(%d) is not found.", sslid_service->service_handle);
1342 goto read_replication_data_out;
1344 if (srv->lsock == NULL) {
1345 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1346 "Conn of service that has handle(%d) is NULL pointer.", sslid_service->service_handle);
1347 goto read_replication_data_out;
1350 /* get replication area address */
1351 data_addr = sslid_protomod.replication_pay_memory(sslid_protomod.modname, &data_size);
1352 if (data_addr == NULL || data_size <= 0)
1353 goto read_replication_data_out;
1355 /* check replication area header */
1356 for (srv_num = 0; srv_num < SSLID_SERVICE_NUMBER; srv_num++) {
1357 head = (struct replication_header*) data_addr + srv_num;
1360 if (data_size * DATA_SIZE < sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used) {
1361 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Over replication area.");
1362 goto read_replication_data_out;
1365 if (pick == NULL && head->size == 0)
1367 if (exist >= 0 && pick != NULL)
1370 /* match ip and port, this is pre-used session information */
1371 if (memcmp(&head->sin_addr, &srv->lsock->addr.sin_addr, sizeof(struct in_addr)) == 0 &&
1372 head->sin_port == srv->lsock->addr.sin_port) {
1378 head = (struct replication_header*) data_addr + exist;
1380 /* restore session information */
1381 if (sslid_service->maxlist * sizeof(struct ssl_session) > head->size) {
1382 // resize if maxlist set bigger than old
1384 /* area size check */
1385 if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1386 used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1387 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1388 "Replication area is full.");
1389 goto read_replication_data_out;
1392 memcpy(sslid_service->session, (char*) data_addr + head->offset, head->size);
1393 memset(sslid_service->replication_addr, 0, head->size);
1394 sslid_service->replication_addr = (char*) data_addr +
1395 sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1396 pick->sin_addr = srv->lsock->addr.sin_addr;
1397 pick->sin_port = srv->lsock->addr.sin_port;
1398 pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1399 pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1401 /*-------- DEBUG LOG --------*/
1402 if (sslid_protomod.get_log_level != NULL &&
1403 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1404 char head_str[DEBUG_STR_LEN];
1405 replication_header_c_str(head_str, pick);
1406 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1407 "Write replication area: head=(%s)", head_str);
1409 /*------ DEBUG LOG END ------*/
1411 // you should garbage old session area...
1415 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1416 "Replication area is full.");
1417 goto read_replication_data_out;
1421 sslid_service->replication_addr = (char*) data_addr + head->offset;
1422 memcpy(sslid_service->session, sslid_service->replication_addr,
1423 sslid_service->maxlist * sizeof(struct ssl_session));
1424 head->size = sslid_service->maxlist * sizeof(struct ssl_session);
1426 /*-------- DEBUG LOG --------*/
1427 if (sslid_protomod.get_log_level != NULL &&
1428 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1429 char head_str[DEBUG_STR_LEN];
1430 replication_header_c_str(head_str, head);
1431 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1432 "Write replication area: head=(%s)", head_str);
1434 /*------ DEBUG LOG END ------*/
1440 /* area size check */
1441 if (sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) +
1442 used + sslid_service->maxlist * sizeof(struct ssl_session) > data_size * DATA_SIZE) {
1443 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1444 "Replication area is full.");
1445 goto read_replication_data_out;
1448 /* initialize replication information */
1449 sslid_service->replication_addr = (char*) data_addr +
1450 sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1451 pick->sin_addr = srv->lsock->addr.sin_addr;
1452 pick->sin_port = srv->lsock->addr.sin_port;
1453 pick->size = sslid_service->maxlist * sizeof(struct ssl_session);
1454 pick->offset = sizeof(struct replication_header) * (SSLID_SERVICE_NUMBER - 1) + used;
1456 /*-------- DEBUG LOG --------*/
1457 if (sslid_protomod.get_log_level != NULL &&
1458 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1459 char head_str[DEBUG_STR_LEN];
1460 replication_header_c_str(head_str, pick);
1461 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1462 "Write replication area: head=(%s)", head_str);
1464 /*------ DEBUG LOG END ------*/
1468 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0,
1469 "Replication area is full.");
1470 goto read_replication_data_out;
1474 read_replication_data_out:
1475 /*-------- DEBUG LOG --------*/
1476 if (sslid_protomod.get_log_level != NULL &&
1477 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1478 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,132,
1479 "out_function: l7vs_protomod_sslid_read_replication_data(struct "
1480 "l7vs_sslid_service* sslid_service)");
1482 /*------ DEBUG LOG END ------*/
1486 * Write session data to replication area.
1487 * @param[in] sslid_service save this sslid service's session.
1490 static void l7vs_protomod_sslid_write_replication_data(struct l7vs_sslid_service* sslid_service)
1492 /*-------- DEBUG LOG --------*/
1493 if (sslid_protomod.get_log_level != NULL &&
1494 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1495 char ssl_str[DEBUG_STR_LEN] = {0};
1496 l7vs_sslid_service_c_str(ssl_str, sslid_service);
1497 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,133,
1498 "in_function: void l7vs_protomod_sslid_write_replication_data(struct "
1499 "l7vs_sslid_service* sslid_service):sslid_service=&(%s)", ssl_str);
1501 /*------ DEBUG LOG END ------*/
1504 if (sslid_service == NULL) {
1505 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service) is NULL pointer.");
1506 goto write_replication_data_out;
1508 if (sslid_service->session == NULL) {
1509 PUT_LOG_ERROR(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Arg(sslid_service->session) is NULL pointer.");
1510 goto write_replication_data_out;
1512 /* no replicate setting */
1513 if (sslid_service->replication_addr == NULL) {
1514 goto write_replication_data_out;
1517 /* copy session data */
1518 memcpy(sslid_service->replication_addr, sslid_service->session,
1519 sizeof(struct ssl_session) * sslid_service->maxlist);
1521 /*-------- DEBUG LOG --------*/
1522 if (sslid_protomod.get_log_level != NULL &&
1523 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1524 char session_str[DEBUG_STR_LEN];
1525 ssl_session_c_str(session_str, (struct ssl_session*) sslid_service->replication_addr);
1526 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL, 0, "Write replication area: session=(%s)",
1529 /*------ DEBUG LOG END ------*/
1531 write_replication_data_out:
1532 /*-------- DEBUG LOG --------*/
1533 if (sslid_protomod.get_log_level != NULL &&
1534 LOG_LV_DEBUG == sslid_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1535 PUT_LOG_DEBUG(sslid_protomod, LOG_CAT_L7VSD_PROTOCOL,134,
1536 "out_function: void l7vs_protomod_sslid_write_replication_data(struct "
1537 "l7vs_sslid_service* sslid_service)");
1539 /*------ DEBUG LOG END ------*/
1543 * Serialize struct l7vs_sslid_service for debug log.
1544 * @param[out] buf serialized string
1545 * @param[in] sslid l7vs_sslid_service struct
1547 static void l7vs_sslid_service_c_str(char* buf, struct l7vs_sslid_service* sslid) {
1548 if (sslid == NULL) {
1549 snprintf(buf, DEBUG_STR_LEN, "NULL");
1552 char session_str[DEBUG_STR_LEN] = {0};
1553 ssl_session_c_str(session_str, sslid->session);
1554 snprintf(buf, DEBUG_STR_LEN, "service_handle=%d, timeout=%d, maxlist=%d, "
1555 "session=(%s), replication_addr=%p, reschedule=%d", sslid->service_handle,
1556 sslid->timeout, sslid->maxlist, session_str, sslid->replication_addr,
1562 * Serialize struct l7vs_sslid_service_arg for debug log.
1563 * @param[out] buf serialized string
1564 * @param[in] sslid_arg l7vs_sslid_service_arg struct
1566 void l7vs_sslid_service_arg_c_str(char* buf, struct l7vs_sslid_service_arg* sslid_arg) {
1567 if (sslid_arg == NULL) {
1568 snprintf(buf, DEBUG_STR_LEN, "NULL");
1571 snprintf(buf, DEBUG_STR_LEN, "timeout=%d, maxlist=%d, reschedule=%d",
1572 sslid_arg->timeout, sslid_arg->maxlist, sslid_arg->reschedule);
1577 * Serialize struct ssl_session for debug log.
1578 * @param[out] buf serialized string
1579 * @param[in] session ssl_session struct
1581 static void ssl_session_c_str(char* buf, struct ssl_session* session) {
1582 if (session == NULL) {
1583 snprintf(buf, DEBUG_STR_LEN, "NULL");
1586 char dest_str[DEBUG_STR_LEN] = {0};
1587 char session_str[SSLID_LENGTH * 2 + 1];
1588 l7vs_dest_c_str(dest_str, &session->dest);
1589 id_c_str(session_str, session->id);
1590 snprintf(buf, DEBUG_STR_LEN, "id=%s, dest=(%s), last_time=%d, valid=%d",
1591 session_str, dest_str, (u_int) session->last_time, (int)session->valid);
1596 * Serialize struct replication_header for debug log.
1597 * @param[out] buf serialized string
1598 * @param[in] head replication_header struct
1600 static void replication_header_c_str(char* buf, struct replication_header* head) {
1602 snprintf(buf, DEBUG_STR_LEN, "NULL");
1605 snprintf(buf, DEBUG_STR_LEN, "sin_addr=(s_addr=%ld), sin_port=%d, size=%d, offset=%d",
1606 (u_long) head->sin_addr.s_addr, head->sin_port, head->size, head->offset);
1611 * Convert SSL session ID (binary to hex)
1612 * @param[out] buf hex string
1613 * @param[in] id SSL session ID
1615 static void id_c_str(char* buf, char* id) {
1618 snprintf(buf, DEBUG_STR_LEN, "NULL");
1621 for (i = 0; i < SSLID_LENGTH; i++) {
1622 snprintf(buf + i * 2, DEBUG_STR_LEN - i * 2, "%02X", (unsigned int)id[i]);