3 * @brief protocol module of HTTP.
4 * @brief this module provide session persistence by URL.
6 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
7 * Copyright (C) 2008 NTT COMWARE Corporation.
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
24 **********************************************************************/
26 #define __STDC_LIMIT_MACROS
32 #include "l7vs_service.h"
33 #include "l7vs_conn.h"
34 #include "l7vs_dest.h"
35 #include "l7vs_module.h"
36 #include "module_http.h"
40 #ifdef USE_BOOST_XPRESSIVE
41 #include <boost/xpressive/xpressive.hpp>
43 #include <boost/regex.hpp>
46 #define SERVICE_ARG_MAXSIZE (512)
47 #define PATTERN_MATCH_MAXSIZE (128)
48 #define REGEX_PATTERN_MATCH_MAXSIZE (32)
49 #define URL_SERVICE_NUMBER (128)
50 #define X_FORWARDED_FOR_LENGTH (48)
52 struct l7vs_url_service {
53 handle_t service_handle;
54 char pattern_match[PATTERN_MATCH_MAXSIZE];
55 char uri_pattern_match[REGEX_PATTERN_MATCH_MAXSIZE];
56 char host_pattern_match[REGEX_PATTERN_MATCH_MAXSIZE];
58 #ifdef USE_BOOST_XPRESSIVE
59 boost::xpressive::sregex uri_regex;
60 boost::xpressive::sregex host_regex;
62 boost::regex uri_regex;
63 boost::regex host_regex;
68 struct l7vs_url_service_arg {
69 char pattern_match[PATTERN_MATCH_MAXSIZE];
70 char uri_pattern_match[REGEX_PATTERN_MATCH_MAXSIZE];
71 char host_pattern_match[REGEX_PATTERN_MATCH_MAXSIZE];
76 static void fini(void);
77 static int create(void*, handle_t);
78 static void* create_sa(struct l7vs_service_arg*);
79 static int compare(handle_t, handle_t);
80 static int select_dest(struct l7vs_service*, struct l7vs_conn*,
81 char*, size_t*, struct l7vs_dest**);
82 static int analyze_cldata(struct l7vs_service*, struct l7vs_conn*,
84 static int analyze_rsdata(struct l7vs_service*, struct l7vs_conn*,
86 static int destroy(handle_t);
87 static void destroy_sa(void**);
88 static int service_arg(struct l7vs_service_arg_multi*, handle_t);
89 static int parse(void*, int, char**);
91 static struct l7vs_url_service *l7vs_protomod_url_search_service(handle_t);
92 static struct l7vs_url_service *l7vs_protomod_url_create_service();
93 static struct l7vs_url_service *l7vs_protomod_url_create_temp_service();
95 static void l7vs_url_service_c_str(char*, struct l7vs_url_service*);
96 static void l7vs_url_service_arg_c_str(char*, struct l7vs_url_service_arg*);
98 struct l7vs_url_service *url_service_list[URL_SERVICE_NUMBER];
100 static struct l7vs_protomod url_protomod = {
104 0, /* fast schedule */
105 create, /* create function */
106 compare, /* compare function */
107 select_dest, /* select_dest function */
108 analyze_cldata, /* analyze_cldata function */
109 analyze_rsdata, /* analyze_rsdata function */
110 destroy, /* destroy function */
111 fini, /* fini function */
112 create_sa, /* create_sa function */
113 service_arg, /* service_arg function */
114 parse, /* parse function */
115 destroy_sa, /* destroy_sa function */
116 NULL, /* initialize function */
117 NULL, /* finalize function */
118 NULL, /* get_log_level function */
119 NULL, /* put_log_debug function */
120 NULL, /* put_log_info function */
121 NULL, /* put_log_warn function */
122 NULL, /* put_log_error function */
123 NULL /* put_log_fatal function */
127 * Protocol module initialize function. This function run when dlopen and dlsym at first time.
128 * @param[in] handle dlopen's handle
129 * @return l7vs_protomod struct
131 extern "C" struct l7vs_protomod *
134 struct l7vs_protomod* return_value = NULL;
136 /*-------- DEBUG LOG --------*/
137 if (url_protomod.get_log_level != NULL &&
138 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
139 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,135,
140 "in_function: struct l7vs_protomod* init(void* handle): handle=%p", handle);
142 /*------ DEBUG LOG END ------*/
145 if (handle == NULL) {
146 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,117, "Arg(handle) is NULL pointer.");
150 /* initialize url service list */
151 memset(url_service_list, 0, sizeof(struct l7vs_url_service *) * URL_SERVICE_NUMBER);
152 /* set dlopen's handle */
153 url_protomod.handle = handle;
155 return_value = &url_protomod;
158 /*-------- DEBUG LOG --------*/
159 if (url_protomod.get_log_level != NULL &&
160 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
161 char protomod_str[DEBUG_STR_LEN] = {0};
162 l7vs_protomod_c_str(protomod_str, &url_protomod);
163 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,136,
164 "out_function: struct l7vs_protomod* init(void* handle): return=&(%s)", protomod_str);
166 /*------ DEBUG LOG END ------*/
171 * Protocol module finalize function. free all url service list just in case.
178 /* url service list counter */
179 int service_number = 0;
181 /*-------- DEBUG LOG --------*/
182 if (url_protomod.get_log_level != NULL &&
183 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
184 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,137, "in_function: void fini(void)");
186 /*------ DEBUG LOG END ------*/
188 /* check all url service list */
189 for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
190 /* if pointer that does not point NULL exists ... */
191 if (url_service_list[service_number] != NULL) {
193 /*-------- DEBUG LOG --------*/
194 if (url_protomod.get_log_level != NULL &&
195 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
196 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,34, "free: %p",
197 url_service_list[service_number]);
199 /*------ DEBUG LOG END ------*/
201 /* free and points NULL */
202 free(url_service_list[service_number]);
203 url_service_list[service_number] = NULL;
206 /*-------- DEBUG LOG --------*/
207 if (url_protomod.get_log_level != NULL &&
208 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
209 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,138, "out_function: void fini(void)");
211 /*------ DEBUG LOG END ------*/
215 * Create url service struct.
216 * @param url_arg url service argument struct
217 * @param service_handle a unique service ID
218 * @retval 0 successfully create url service.
219 * @retval -1 some errors occur.
222 create(void *url_arg, handle_t service_handle)
224 struct l7vs_url_service *url_service;
225 struct l7vs_url_service_arg *url_service_arg;
226 int return_value = 0;
228 /*-------- DEBUG LOG --------*/
229 if (url_protomod.get_log_level != NULL &&
230 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
231 char url_arg_str[DEBUG_STR_LEN] = {0};
232 l7vs_url_service_arg_c_str(url_arg_str, (struct l7vs_url_service_arg*) url_arg);
233 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,139,
234 "in_function: int create(void* url_arg, handle_t service_handle):url_arg=&(%s), "
235 "service_handle=%d", url_arg_str, service_handle);
237 /*------ DEBUG LOG END ------*/
240 if (url_arg == NULL) {
241 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,118, "Arg(url_arg) is NULL pointer.");
246 if (service_handle != TEMP_SERVICEHANDLE) {
247 /* search empty url service list and create url service */
248 url_service = l7vs_protomod_url_create_service();
250 /* create temporary url service */
251 url_service = l7vs_protomod_url_create_temp_service();
254 /*-------- DEBUG LOG --------*/
255 if (url_protomod.get_log_level != NULL &&
256 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
257 char url_str[DEBUG_STR_LEN] = {0};
258 l7vs_url_service_c_str(url_str, url_service);
259 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,140, "pointer assign: url_service=&(%s)",
262 /*------ DEBUG LOG END ------*/
264 if (url_service == NULL) {
265 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,119, "Could not make url service.");
270 url_service_arg = (struct l7vs_url_service_arg *) url_arg;
272 /* set service handle, pattern match and reschedule flag */
273 url_service->service_handle = service_handle;
274 strncpy(url_service->pattern_match, url_service_arg->pattern_match, PATTERN_MATCH_MAXSIZE);
275 strncpy(url_service->uri_pattern_match, url_service_arg->uri_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE);
276 strncpy(url_service->host_pattern_match, url_service_arg->host_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE);
277 url_service->forwarded_for = url_service_arg->forwarded_for;
278 if ( strnlen(url_service_arg->uri_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) ) {
280 #ifdef USE_BOOST_XPRESSIVE
281 url_service->uri_regex = boost::xpressive::sregex::compile(url_service_arg->uri_pattern_match);
283 url_service->uri_regex.assign(url_service_arg->uri_pattern_match);
287 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,284, "Regex pattern error of uri_pattern_match");
292 if ( strnlen(url_service_arg->host_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) ) {
294 #ifdef USE_BOOST_XPRESSIVE
295 url_service->host_regex = boost::xpressive::sregex::compile(url_service_arg->host_pattern_match);
297 url_service->host_regex.assign(url_service_arg->host_pattern_match);
301 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,285, "Regex pattern error of host_pattern_match.");
306 url_service->reschedule = url_service_arg->reschedule;
309 /*-------- DEBUG LOG --------*/
310 if (url_protomod.get_log_level != NULL &&
311 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
312 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,141,
313 "out_function: int create(void* url_arg, handle_t service_handle):return_value=%d",
316 /*------ DEBUG LOG END ------*/
322 * Create url service argument struct.
323 * @param[out] srv_arg service argument struct
324 * @return url service argument struct
327 create_sa(struct l7vs_service_arg *srv_arg)
329 struct l7vs_url_service_arg *url_service_arg;
331 /*-------- DEBUG LOG --------*/
332 if (url_protomod.get_log_level != NULL &&
333 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
334 char service_arg_str[DEBUG_STR_LEN] = {0};
335 l7vs_service_arg_c_str(service_arg_str, srv_arg);
336 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,142,
337 "in_function: void* create_sa(struct l7vs_service_arg* srv_arg):srv_arg=&(%s)",
340 /*------ DEBUG LOG END ------*/
343 if (srv_arg == NULL) {
344 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,120, "Arg(srv_arg) is NULL pointer.");
345 url_service_arg = NULL;
349 /* create url service argument struct */
350 url_service_arg = (struct l7vs_url_service_arg *) calloc(1, sizeof(struct l7vs_url_service_arg));
352 /*-------- DEBUG LOG --------*/
353 if (url_protomod.get_log_level != NULL &&
354 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
355 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,35, "calloc: addr=%p, size=%ld",
356 url_service_arg, (unsigned long int) sizeof(struct l7vs_url_service_arg));
358 /*------ DEBUG LOG END ------*/
360 if (url_service_arg == NULL) {
361 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,27, "Could not allocate memory.");
365 /* set url service argument size and protomod name "url" */
366 srv_arg->len = sizeof(struct l7vs_url_service_arg);
367 strcpy(srv_arg->protomod, url_protomod.modname);
370 /*-------- DEBUG LOG --------*/
371 if (url_protomod.get_log_level != NULL &&
372 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
373 char url_service_arg_str[DEBUG_STR_LEN] = {0};
374 l7vs_url_service_arg_c_str(url_service_arg_str, url_service_arg);
375 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,143,
376 "out_function: void* create_sa(struct l7vs_service_arg* srv_arg):return_value=&(%s)",
377 url_service_arg_str);
379 /*------ DEBUG LOG END ------*/
381 return (void*) url_service_arg;
385 * Compare two service.
386 * @param[in] srv_handle1 one of a unique service ID
387 * @param[in] srv_handle2 one of a unique service ID
388 * @retval 0 they matched perfectly.
389 * @retval -1 they are different.
392 compare(handle_t srv_handle1, handle_t srv_handle2)
394 struct l7vs_url_service *url_srv1, *url_srv2;
395 int return_value = 0;
397 /*-------- DEBUG LOG --------*/
398 if (url_protomod.get_log_level != NULL &&
399 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
400 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,144,
401 "in_function: int compare(handle_t srv_handle1, handle_t srv_handle2):"
402 "srv_handle1=%u, srv_handle2=%u", srv_handle1, srv_handle2);
404 /*------ DEBUG LOG END ------*/
406 /* search service that has such a service ID(1) */
407 url_srv1 = l7vs_protomod_url_search_service(srv_handle1);
409 /*-------- DEBUG LOG --------*/
410 if (url_protomod.get_log_level != NULL &&
411 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
412 char url_str[DEBUG_STR_LEN] = {0};
413 l7vs_url_service_c_str(url_str, url_srv1);
414 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,145, "pointer assign: url_srv1=&(%s)",
417 /*------ DEBUG LOG END ------*/
419 if (url_srv1 == NULL) {
420 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,121,
421 "Could not find such service handle's url service.");
426 /* search service that has such a service ID(2) */
427 url_srv2 = l7vs_protomod_url_search_service(srv_handle2);
429 /*-------- DEBUG LOG --------*/
430 if (url_protomod.get_log_level != NULL &&
431 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
432 char url_str[DEBUG_STR_LEN] = {0};
433 l7vs_url_service_c_str(url_str, url_srv2);
434 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,146, "pointer assign: url_srv2=&(%s)",
437 /*------ DEBUG LOG END ------*/
439 if (url_srv2 == NULL) {
440 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,122,
441 "Could not find such service handle's url service.");
446 /* compare two pattern match */
447 if (strncmp(url_srv1->pattern_match, url_srv2->pattern_match, PATTERN_MATCH_MAXSIZE) != 0) {
451 if (strncmp(url_srv1->uri_pattern_match, url_srv2->uri_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) != 0) {
455 if (strncmp(url_srv1->host_pattern_match, url_srv2->host_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) != 0) {
461 /*-------- DEBUG LOG --------*/
462 if (url_protomod.get_log_level != NULL &&
463 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
464 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,147,
465 "out_function: int compare(handle_t srv_handle1, handle_t srv_handle2):return_value=%d",
468 /*------ DEBUG LOG END ------*/
474 * Check the client packet and determine a real server.
475 * @param[in] srv service struct include service handle, protocol module and schedule module.
476 * @param[in] conn connection data.
477 * @param[in] request packet data from client
478 * @param[in] len length of packet data
479 * @param[out] dest destination (real server) list
480 * @retval 0 successfully check packet data
481 * @retval -1 some errors occur.
484 select_dest(struct l7vs_service *srv, struct l7vs_conn *conn,
485 char *request, size_t *len, struct l7vs_dest **dest)
487 struct l7vs_url_service *url_service;
490 int asterisk_num = 0;
493 char *uri, *host, pattern[PATTERN_MATCH_MAXSIZE + 2];
495 char *x_forwarded_value;
496 char *next_line = NULL;
497 char x_forwarded_for_header[X_FORWARDED_FOR_LENGTH];
499 int return_value = 0;
501 std::string packet_data;
503 /*-------- DEBUG LOG --------*/
504 if (url_protomod.get_log_level != NULL &&
505 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
506 char srv_str[DEBUG_STR_LEN] = {0};
507 char conn_str[DEBUG_STR_LEN] = {0};
508 char dest_str[DEBUG_STR_LEN] = {0};
509 char len_str[DEBUG_STR_LEN] = {0};
510 char tcps_str[DEBUG_STR_LEN] = {0};
511 l7vs_service_c_str(srv_str, srv);
512 l7vs_conn_c_str(conn_str, conn);
514 l7vs_dest_c_str(dest_str, *dest);
517 strncpy(dest_str, "NULL", DEBUG_STR_LEN);
520 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
523 strncpy(len_str, "NULL", DEBUG_STR_LEN);
525 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,148,
526 "in_function: int select_dest(struct l7vs_service* srv, struct l7vs_conn* conn, "
527 "char* request, size_t* len, struct l7vs_dest** dest):srv=&(%s), conn=&(%s), "
528 "request=\"%s\", len=&(%s), dest=&(&(%s))",
529 srv_str, conn_str, request, len_str, dest_str);
531 /*------ DEBUG LOG END ------*/
535 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,123, "Arg(srv) is NULL pointer.");
537 goto select_dest_out;
539 if (srv->pm == NULL) {
540 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,124, "Arg(srv->pm) is NULL pointer.");
542 goto select_dest_out;
544 if (request == NULL) {
545 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,125, "Arg(request) is NULL pointer.");
547 goto select_dest_out;
550 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,126, "Arg(len) is NULL pointer.");
552 goto select_dest_out;
555 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,127, "Arg(dest) is NULL pointer.");
557 goto select_dest_out;
560 /* search service that has such a service ID */
561 url_service = l7vs_protomod_url_search_service(srv->handle);
563 /*-------- DEBUG LOG --------*/
564 if (url_protomod.get_log_level != NULL &&
565 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
566 char url_str[DEBUG_STR_LEN] = {0};
567 l7vs_url_service_c_str(url_str, url_service);
568 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,149, "pointer assign: url_service=&(%s)",
571 /*------ DEBUG LOG END ------*/
573 if (url_service == NULL) {
574 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,129, "Could not find such service handle's url service.");
576 goto select_dest_out;
579 /* initialize protocol module ... clear destination list */
580 ret = srv->pm->initialize(srv, conn, request, *len, dest);
582 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,130, "Could not initialize protomod.");
584 goto select_dest_out;
587 /* check pattern_match length */
588 if (url_service->pattern_match[0] != '\0') {
589 /* check the size of request data */
590 pattern_len = strnlen(url_service->pattern_match, PATTERN_MATCH_MAXSIZE);
591 /* When '*' is included in pattern_match, number of '*' is decreased from pattern_len */
592 for (i = 0; i < (int)pattern_len; i++) {
593 if (url_service->pattern_match[i] == '*') {
597 pattern_len -= (size_t)asterisk_num;
598 if (*len < (15 + pattern_len) ) {
599 PUT_LOG_INFO(url_protomod, LOG_CAT_L7VSD_PROTOCOL,6, "Request data is too short.");
601 goto select_dest_out;
605 /* check the HTTP method in HTTP request header */
607 uri = http_check_request_method(request, &uri_len);
609 PUT_LOG_INFO(url_protomod, LOG_CAT_L7VSD_PROTOCOL,7, "Client message is not HTTP request.");
611 goto select_dest_out;
614 /* check keyword (URI/--uri-pattern-match)*/
615 if (url_service->uri_pattern_match[0] != '\0') {
616 packet_data = std::string(uri, uri_len);
617 #ifdef USE_BOOST_XPRESSIVE
618 if ( !boost::xpressive::regex_search(packet_data, url_service->uri_regex) ) {
620 if ( !boost::regex_search(packet_data, url_service->uri_regex) ) {
623 goto select_dest_out;
626 /* check keyword (URI/--pattern-match)*/
627 if (url_service->pattern_match[0] != '\0') {
628 backup_char = uri[uri_len];
630 snprintf(pattern, pattern_len + 3, "*%s*", url_service->pattern_match);
631 ret = fnmatch(pattern, uri, 0);
632 uri[uri_len] = backup_char;
634 if ( (url_service->pattern_match[0] != '\0' && ret != 0) ||
635 (url_service->host_pattern_match[0] != '\0') ) {
637 /* search Host field in HTTP request header */
638 host = http_search_header_field(request, "Host");
640 PUT_LOG_INFO(url_protomod, LOG_CAT_L7VSD_PROTOCOL,8, "Could not find Host field.");
642 goto select_dest_out;
645 next_line = http_skip_header_line(host);
647 next_line--; // *next_line == '\n'
648 if (*(next_line - 1) == '\r') {
651 /* check keyword (HOST/--host-pattern-match) */
652 if (url_service->host_pattern_match[0] != '\0') {
653 packet_data = std::string(host, next_line - host);
654 #ifdef USE_BOOST_XPRESSIVE
655 if ( !boost::xpressive::regex_search(packet_data, url_service->host_regex) ) {
657 if ( !boost::regex_search(packet_data, url_service->host_regex) ) {
660 goto select_dest_out;
663 /* check keyword (HOST/--pattern-match) */
664 if (url_service->pattern_match[0] != '\0' && ret != 0) {
665 backup_char = *next_line;
667 ret = fnmatch(pattern, host, 0);
668 *next_line = backup_char;
671 goto select_dest_out;
680 ret = srv->pm->finalize(srv, conn, request, *len, dest, url_service->reschedule);
682 PUT_LOG_INFO(url_protomod, LOG_CAT_L7VSD_PROTOCOL,12, "Could not finalize protomod. (Realserver decision failure)");
684 goto select_dest_out;
688 /*-------- DEBUG LOG --------*/
689 if (url_protomod.get_log_level != NULL &&
690 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
691 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,150,
692 "out_function: int select_dest(struct l7vs_service* srv, struct l7vs_conn* conn, "
693 "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):return_value=%d",
696 /*------ DEBUG LOG END ------*/
702 * Analyze and modify client packet
703 * @param[in] srv service struct include service handle, protocol module and schedule module.
704 * @param[in] conn connection data.
705 * @param[in] request packet data from client
706 * @param[in] len length of packet data
707 * @retval 0 successfully check packet data
708 * @retval -1 some errors occur.
711 analyze_cldata(struct l7vs_service *srv, struct l7vs_conn *conn,
712 char *request, size_t *len)
714 struct l7vs_url_service *url_service;
717 int asterisk_num = 0;
720 char *uri, *host, pattern[PATTERN_MATCH_MAXSIZE + 2];
722 char *x_forwarded_value;
723 char *next_line = NULL;
724 char x_forwarded_for_header[X_FORWARDED_FOR_LENGTH];
726 int return_value = 0;
728 std::string packet_data;
730 /*-------- DEBUG LOG --------*/
731 if (url_protomod.get_log_level != NULL &&
732 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
733 char srv_str[DEBUG_STR_LEN] = {0};
734 char conn_str[DEBUG_STR_LEN] = {0};
735 char len_str[DEBUG_STR_LEN] = {0};
736 l7vs_service_c_str(srv_str, srv);
737 l7vs_conn_c_str(conn_str, conn);
739 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
742 strncpy(len_str, "NULL", DEBUG_STR_LEN);
744 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,148,
745 "in_function: int analyze_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
746 "char* request, size_t* len):srv=&(%s), conn=&(%s), "
747 "request=\"%s\", len=&(%s)",
748 srv_str, conn_str, request, len_str);
750 /*------ DEBUG LOG END ------*/
754 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,123, "Arg(srv) is NULL pointer.");
756 goto analyze_cldata_out;
758 if (srv->pm == NULL) {
759 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,124, "Arg(srv->pm) is NULL pointer.");
761 goto analyze_cldata_out;
763 if (request == NULL) {
764 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,125, "Arg(request) is NULL pointer.");
766 goto analyze_cldata_out;
769 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,126, "Arg(len) is NULL pointer.");
771 goto analyze_cldata_out;
774 /* search service that has such a service ID */
775 url_service = l7vs_protomod_url_search_service(srv->handle);
777 /*-------- DEBUG LOG --------*/
778 if (url_protomod.get_log_level != NULL &&
779 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
780 char url_str[DEBUG_STR_LEN] = {0};
781 l7vs_url_service_c_str(url_str, url_service);
782 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,149, "pointer assign: url_service=&(%s)",
785 /*------ DEBUG LOG END ------*/
787 if (url_service == NULL) {
788 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,129, "Could not find such service handle's url service.");
790 goto analyze_cldata_out;
793 /* add X-Forwarded-For field */
794 if (url_service->forwarded_for) {
795 x_forwarded_value = http_search_header_field(request, "X-Forwarded-For");
797 /* already exists X-Forwarded-For field */
798 if (x_forwarded_value) {
799 next_line = http_skip_header_line(x_forwarded_value);
800 /* backtrack to look up insert point */
802 next_line--; // *next_line == '\n'
803 if (*(next_line - 1) == '\r') {
806 /* append client IP address */
807 snprintf(x_forwarded_for_header, X_FORWARDED_FOR_LENGTH, ", %s", inet_ntoa(conn->caddr.sin_addr));
811 /* not exists X-Forwarded-For field */
813 /* construct new X-Forwarded-For header item */
814 snprintf(x_forwarded_for_header, X_FORWARDED_FOR_LENGTH, "X-Forwarded-For: %s\r\n", inet_ntoa(conn->caddr.sin_addr));
816 next_line = http_skip_header_line(request);
819 /* when insert point exist */
820 if (next_line != NULL) {
821 offset_length = (int) (next_line - request);
823 /* insert X-Forwarded-For header field */
824 http_insert_field(request, offset_length, x_forwarded_for_header, *len);
826 /* add header length */
827 *len += strlen(x_forwarded_for_header);
832 /*-------- DEBUG LOG --------*/
833 if (url_protomod.get_log_level != NULL &&
834 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
835 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,150,
836 "out_function: int analyze_cldata(struct l7vs_service* srv, struct l7vs_conn* conn, "
837 "char* request, size_t* len, struct l7vs_dest** dest, int* tcps):return_value=%d",
840 /*------ DEBUG LOG END ------*/
846 * Check the real server packet and insert a Set-Cookie field.
847 * @param[in] srv service struct include service handle, protocol module and schedule module.
848 * @param[in] conn connection data.
849 * @param[in] response packet data from real server
850 * @param[in] len length of packet data. it will be lengthened.
851 * @retval 0 successfully check packet data.
852 * @retval -1 some errors occur.
855 analyze_rsdata(struct l7vs_service *srv, struct l7vs_conn *conn,
856 char *response, size_t *len)
858 int return_value = 0;
860 /*-------- DEBUG LOG --------*/
861 if (url_protomod.get_log_level != NULL &&
862 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
863 char srv_str[DEBUG_STR_LEN] = {0};
864 char conn_str[DEBUG_STR_LEN] = {0};
865 char len_str[DEBUG_STR_LEN] = {0};
866 l7vs_service_c_str(srv_str, srv);
867 l7vs_conn_c_str(conn_str, conn);
869 snprintf(len_str, DEBUG_STR_LEN, "%lu", (unsigned long int) *len);
872 strncpy(len_str, "NULL", DEBUG_STR_LEN);
874 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,151,
875 "in_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
876 "char* response, size_t* len):srv=&(%s), conn=&(%s), response=\"%s\", len=&(%s)",
877 srv_str, conn_str, response, len_str);
879 /*------ DEBUG LOG END ------*/
883 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,133, "Arg(srv) is NULL pointer.");
885 goto analyze_rsdata_out;
888 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,134, "Arg(conn) is NULL pointer.");
890 goto analyze_rsdata_out;
892 if (conn->dest == NULL) {
893 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,135, "Arg(conn->dest) is NULL pointer.");
895 goto analyze_rsdata_out;
897 if (response == NULL) {
898 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,136, "Arg(response) is NULL pointer.");
900 goto analyze_rsdata_out;
903 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,137, "Arg(len) is NULL pointer.");
905 goto analyze_rsdata_out;
908 /* sorry flag check */
909 if (conn->sorry_conn_flag == 1) {
910 /*-------- DEBUG LOG --------*/
911 if (url_protomod.get_log_level != NULL &&
912 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
913 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,152, "Response from sorry server.");
915 /*------ DEBUG LOG END ------*/
916 goto analyze_rsdata_out;
920 /*-------- DEBUG LOG --------*/
921 if (url_protomod.get_log_level != NULL &&
922 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
923 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,153,
924 "out_function: int analyze_rsdata(struct l7vs_service* srv, struct l7vs_conn* conn, "
925 "char* response, size_t* len):return_value=%d", return_value);
927 /*------ DEBUG LOG END ------*/
933 * Destroy url service
934 * @param[in] srv_handle a unique service ID
935 * @retval 0 successfully check packet data.
936 * @retval -1 some errors occur.
939 destroy(handle_t srv_handle)
941 /* url service list counter */
942 int service_number = 0;
944 int return_value = 0;
946 /*-------- DEBUG LOG --------*/
947 if (url_protomod.get_log_level != NULL &&
948 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
949 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,154,
950 "in_function: int destroy(handle_t srv_handle):srv_handle=%u",
953 /*------ DEBUG LOG END ------*/
955 /* check all url service list */
956 for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
957 /* found url service that has srv_handle */
958 if (url_service_list[service_number] != NULL &&
959 url_service_list[service_number]->service_handle == srv_handle) {
961 /*-------- DEBUG LOG --------*/
962 if (url_protomod.get_log_level != NULL &&
963 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
964 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,36, "free: %p",
965 url_service_list[service_number]);
967 /*------ DEBUG LOG END ------*/
970 free(url_service_list[service_number]);
971 url_service_list[service_number] = NULL;
978 /* url service was not found */
979 if (free_flag == 0) {
980 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,138, "Could not find such service handle's url service.");
986 /*-------- DEBUG LOG --------*/
987 if (url_protomod.get_log_level != NULL &&
988 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
989 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,155,
990 "out_function: int destroy(handle_t srv_handle):return_value=%d",
993 /*------ DEBUG LOG END ------*/
999 * Destroy url service argument
1000 * @param[in] url_arg url service argument
1004 destroy_sa(void **url_arg)
1006 /*-------- DEBUG LOG --------*/
1007 if (url_protomod.get_log_level != NULL &&
1008 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1009 char url_arg_str[DEBUG_STR_LEN] = {0};
1010 if (url_arg != NULL) {
1011 l7vs_url_service_arg_c_str(url_arg_str, (struct l7vs_url_service_arg*) *url_arg);
1014 strncpy(url_arg_str, "NULL", DEBUG_STR_LEN);
1016 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,156,
1017 "in_function: void destroy_sa(void** url_arg):url_arg=&(&(%s))",
1020 /*------ DEBUG LOG END ------*/
1023 if (url_arg == NULL) {
1024 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,139, "Arg(url_arg) is NULL pointer.");
1026 else if (*url_arg == NULL) {
1027 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,140, "Arg(*url_arg) is NULL pointer.");
1030 /*-------- DEBUG LOG --------*/
1031 if (url_protomod.get_log_level != NULL &&
1032 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1033 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,37, "free: %p",
1036 /*------ DEBUG LOG END ------*/
1039 free((struct l7vs_url_service_arg*) *url_arg);
1043 /*-------- DEBUG LOG --------*/
1044 if (url_protomod.get_log_level != NULL &&
1045 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1046 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,157,
1047 "out_function: void destroy_sa(void** url_arg)");
1049 /*------ DEBUG LOG END ------*/
1053 * Create strings for service list of l7vsadm
1054 * @param srv_arg service argument struct
1055 * @param srv_handle a unique service ID
1056 * @retval 0 successfully create strings
1057 * @retval -1 some errors occur.
1060 service_arg(struct l7vs_service_arg_multi *srv_arg_mt, handle_t srv_handle)
1062 struct l7vs_url_service *url_service;
1063 struct l7vs_url_service_arg c_sarg;
1064 char url_argument[SERVICE_ARG_MAXSIZE];
1065 int return_value = 0;
1067 /*-------- DEBUG LOG --------*/
1068 if (url_protomod.get_log_level != NULL &&
1069 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1070 char srv_arg_mt_str[DEBUG_STR_LEN] = {0};
1071 l7vs_service_arg_multi_c_str(srv_arg_mt_str, srv_arg_mt);
1072 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,158,
1073 "in_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
1074 "handle_t srv_handle):srv_arg_mt=&(%s), srv_handle=%u",
1075 srv_arg_mt_str, srv_handle);
1077 /*------ DEBUG LOG END ------*/
1080 if (srv_arg_mt == NULL) {
1081 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,141, "Arg(srv_arg_mt) is NULL pointer.");
1083 goto service_arg_out;
1086 /* search service that has such a service ID */
1087 url_service = l7vs_protomod_url_search_service(srv_handle);
1089 /*-------- DEBUG LOG --------*/
1090 if (url_protomod.get_log_level != NULL &&
1091 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1092 char url_str[DEBUG_STR_LEN] = {0};
1093 l7vs_url_service_c_str(url_str, url_service);
1094 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,159, "pointer assign: url_service=&(%s)",
1097 /*------ DEBUG LOG END ------*/
1099 if (url_service == NULL) {
1100 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,142, "Could not find such service handle's url service.");
1102 goto service_arg_out;
1105 /* initialize argument strings */
1106 memset(url_argument, 0, SERVICE_ARG_MAXSIZE);
1108 /* set url args to service argument struct */
1109 srv_arg_mt->srv_arg.reschedule = url_service->reschedule;
1111 /* create long argument (l7vsadm option -L/-l) */
1112 if ( strnlen(url_service->pattern_match, PATTERN_MATCH_MAXSIZE) ) {
1113 snprintf(url_argument, SERVICE_ARG_MAXSIZE, "--pattern-match %s", url_service->pattern_match);
1115 if ( strnlen(url_service->uri_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) ) {
1116 snprintf(url_argument + strlen(url_argument), SERVICE_ARG_MAXSIZE - strlen(url_argument),
1117 " --uri-pattern-match %s", url_service->uri_pattern_match);
1119 if ( strnlen(url_service->host_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE) ) {
1120 snprintf(url_argument + strlen(url_argument), SERVICE_ARG_MAXSIZE - strlen(url_argument),
1121 " --host-pattern-match %s", url_service->host_pattern_match);
1123 strncpy(srv_arg_mt->srv_arg.protomod_key_string, url_argument, 256);
1125 /* create verbose argument (l7vsadm option -V/-v) */
1126 if (url_service->forwarded_for) {
1127 snprintf(url_argument + strlen(url_argument), SERVICE_ARG_MAXSIZE - strlen(url_argument),
1128 " --forwarded-for");
1130 strncpy(srv_arg_mt->srv_arg.protomod_opt_string, url_argument, 512);
1132 strncpy(c_sarg.pattern_match, url_service->pattern_match, PATTERN_MATCH_MAXSIZE);
1133 strncpy(c_sarg.uri_pattern_match, url_service->uri_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE);
1134 strncpy(c_sarg.host_pattern_match, url_service->host_pattern_match, REGEX_PATTERN_MATCH_MAXSIZE);
1135 c_sarg.reschedule = url_service->reschedule;
1137 memcpy(srv_arg_mt->protomod_arg, &c_sarg, sizeof(struct l7vs_url_service_arg));
1139 /*-------- DEBUG LOG --------*/
1140 if (url_protomod.get_log_level != NULL &&
1141 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1142 char url_arg_str[DEBUG_STR_LEN] = {0};
1143 l7vs_url_service_arg_c_str(url_arg_str, &c_sarg);
1144 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,160,
1145 "pointer assign: srv_arg_mt->protomod_arg=&(%s)", url_arg_str);
1147 /*------ DEBUG LOG END ------*/
1150 /*-------- DEBUG LOG --------*/
1151 if (url_protomod.get_log_level != NULL &&
1152 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1153 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,161,
1154 "out_function: int service_arg(struct l7vs_service_arg_multi* srv_arg_mt, "
1155 "handle_t srv_handle):return_value=%d", return_value);
1157 /*------ DEBUG LOG END ------*/
1159 return return_value;
1163 * Parse l7vsadm options to url argument
1164 * @param[out] url_arg url service argument struct
1165 * @param[int] argc number of l7vsadm argument
1166 * @param[int] argv l7vsadm argument list
1167 * @retval 0 successfully parse argument
1168 * @retval -1 some errors occur.
1171 parse(void *url_arg, int argc, char *argv[])
1173 struct l7vs_url_service_arg *url_service_arg;
1174 static struct option opt[] = {
1175 {"pattern-match", required_argument, NULL, 'P'},
1176 {"uri-pattern-match", required_argument, NULL, 'U'},
1177 {"host-pattern-match", required_argument, NULL, 'H'},
1178 {"forwarded-for", no_argument, NULL, 'F'},
1182 int pattern_match_flag = 0;
1183 int uri_pattern_match_flag = 0;
1184 int host_pattern_match_flag = 0;
1185 int forwarded_for_flag = 0;
1186 int return_value = 0;
1187 #ifndef USE_BOOST_XPRESSIVE
1191 /*-------- DEBUG LOG --------*/
1192 if (url_protomod.get_log_level != NULL &&
1193 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1195 char argv_str[DEBUG_STR_LEN] = {0};
1196 char url_arg_str[DEBUG_STR_LEN] = {0};
1197 l7vs_url_service_arg_c_str(url_arg_str, (struct l7vs_url_service_arg*) url_arg);
1200 snprintf(argv_str, DEBUG_STR_LEN, "NULL");
1202 for (i = 0; i < argc; i++) {
1203 snprintf(argv_str, DEBUG_STR_LEN, "%sargv[%d]=\"%s\", ", argv_str, i, argv[i]);
1205 i = strnlen(argv_str, DEBUG_STR_LEN);
1207 argv_str[i - 2] = '\0';
1209 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,162,
1210 "in_function: int parse(void* url_arg, int argc, char* argv[]):url_arg=&(%s), "
1211 "argc=%d, %s", url_arg_str, argc, argv_str);
1213 /*------ DEBUG LOG END ------*/
1216 if (url_arg == NULL) {
1217 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,143, "Arg(url_arg) is NULL pointer.");
1222 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,144, "Arg(argv) is NULL pointer.");
1227 url_service_arg = (struct l7vs_url_service_arg *) url_arg;
1230 /* check all argument */
1231 while ((c = getopt_long(argc, argv, "P:U:H:F", opt, NULL)) != -1) {
1233 /* --pattern-match / -P */
1235 /* check maximum length */
1236 if (strnlen(optarg, PATTERN_MATCH_MAXSIZE) >= PATTERN_MATCH_MAXSIZE) {
1237 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,145,
1238 "-P/--pattern-match option value '%s' too long", optarg);
1242 /* check minimum length */
1243 if (strnlen(optarg, PATTERN_MATCH_MAXSIZE) <= 0 ) {
1244 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,146,
1245 "-P/--pattern-match option value '%s' invalid", optarg);
1249 strncpy(url_service_arg->pattern_match, optarg, PATTERN_MATCH_MAXSIZE);
1250 pattern_match_flag++;
1253 /* --uri-pattern-match / -U */
1255 /* check maximum length */
1256 if (strnlen(optarg, REGEX_PATTERN_MATCH_MAXSIZE) >= REGEX_PATTERN_MATCH_MAXSIZE) {
1257 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,286,
1258 "-U/--uri-pattern-match option value '%s' too long", optarg);
1262 /* check minimum length */
1263 if (strnlen(optarg, REGEX_PATTERN_MATCH_MAXSIZE) <= 0 ) {
1264 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,287,
1265 "-U/--uri-pattern-match option value '%s' invalid", optarg);
1269 strncpy(url_service_arg->uri_pattern_match, optarg, REGEX_PATTERN_MATCH_MAXSIZE);
1270 uri_pattern_match_flag++;
1273 /* --host-pattern-match / -H */
1275 /* check maximum length */
1276 if (strnlen(optarg, REGEX_PATTERN_MATCH_MAXSIZE) >= REGEX_PATTERN_MATCH_MAXSIZE) {
1277 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,288,
1278 "-H/--host-pattern-match option value '%s' too long", optarg);
1282 /* check minimum length */
1283 if (strnlen(optarg, REGEX_PATTERN_MATCH_MAXSIZE) <= 0 ) {
1284 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,289,
1285 "-H/--host-pattern-match option value '%s' invalid", optarg);
1289 strncpy(url_service_arg->host_pattern_match, optarg, REGEX_PATTERN_MATCH_MAXSIZE);
1290 host_pattern_match_flag++;
1293 /* --forwarded-for / -F */
1295 /* x-forwarded-for on */
1296 url_service_arg->forwarded_for = 1;
1297 forwarded_for_flag++;
1302 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,147, "Option error.");
1308 /* set default no forwarded_for */
1309 if (forwarded_for_flag == 0) {
1310 url_service_arg->forwarded_for = 0;
1313 /* set default no reschedule */
1314 url_service_arg->reschedule = 0;
1316 /* no pattern-match value */
1317 if (pattern_match_flag == 0 && uri_pattern_match_flag == 0 && host_pattern_match_flag ==0) {
1318 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,148,
1319 "You have to set any of '--pattern-match', '--uri-pattern-match' or '--host-pattern-match' option.");
1324 if (pattern_match_flag > 1) {
1325 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,149,
1326 "Cannot set multiple option '--pattern-match/-P'.");
1330 if (uri_pattern_match_flag > 1) {
1331 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,290,
1332 "Cannot set multiple option '--uri-pattern-match/-U'.");
1336 if (host_pattern_match_flag > 1) {
1337 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,291,
1338 "Cannot set multiple option '--host-pattern-match/-H'.");
1343 if (uri_pattern_match_flag) {
1345 #ifdef USE_BOOST_XPRESSIVE
1346 boost::xpressive::sregex::compile(url_service_arg->uri_pattern_match);
1348 regex.assign(url_service_arg->uri_pattern_match);
1352 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,292,
1353 "Regex pattern error of option '--uri-pattern-match/-U'.");
1358 if (host_pattern_match_flag) {
1360 #ifdef USE_BOOST_XPRESSIVE
1361 boost::xpressive::sregex::compile(url_service_arg->host_pattern_match);
1363 regex.assign(url_service_arg->host_pattern_match);
1367 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,293,
1368 "Regex pattern error of option '--host-pattern-match/-H'.");
1375 /*-------- DEBUG LOG --------*/
1376 if (url_protomod.get_log_level != NULL &&
1377 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1378 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,163,
1379 "out_function: int parse(void* url_arg, int argc, char* argv[]):return_value=%d",
1382 /*------ DEBUG LOG END ------*/
1384 return return_value;
1388 * Search url service from url service list using service handle
1389 * @param[in] service_handle a unique service ID
1390 * @return url service struct when service was found. NULL when service was not found.
1392 static struct l7vs_url_service *
1393 l7vs_protomod_url_search_service(handle_t service_handle)
1395 /* url service list counter */
1396 int service_number = 0;
1397 struct l7vs_url_service* return_value = NULL;
1399 /*-------- DEBUG LOG --------*/
1400 if (url_protomod.get_log_level != NULL &&
1401 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1402 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,164,
1403 "in_function: struct l7vs_url_service* l7vs_protomod_url_search_service(handle_t service_handle):"
1404 "service_handle=%d", service_handle);
1406 /*------ DEBUG LOG END ------*/
1408 /* check all url service list */
1409 for (service_number = 0; service_number < URL_SERVICE_NUMBER; ++service_number) {
1410 /* found the service has same service handle */
1411 if (url_service_list[service_number] != NULL &&
1412 url_service_list[service_number]->service_handle == service_handle) {
1413 return_value = url_service_list[service_number];
1418 /*-------- DEBUG LOG --------*/
1419 if (url_protomod.get_log_level != NULL &&
1420 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1421 char ssl_str[DEBUG_STR_LEN] = {0};
1422 l7vs_url_service_c_str(ssl_str, return_value);
1423 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,165,
1424 "out_function: struct l7vs_url_service* l7vs_protomod_url_search_service(handle_t service_handle):"
1425 "return_value=&(%s)", ssl_str);
1427 /*------ DEBUG LOG END ------*/
1429 return return_value;
1433 * Create url service.
1435 * @return url service struct when create a service. NULL when cannot create service.
1437 static struct l7vs_url_service *
1438 l7vs_protomod_url_create_service()
1440 struct l7vs_url_service* return_value = NULL;
1441 int service_number = 0;
1443 /*-------- DEBUG LOG --------*/
1444 if (url_protomod.get_log_level != NULL &&
1445 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1446 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,166,
1447 "in_function: struct l7vs_url_service* l7vs_protomod_url_create_service()");
1449 /*------ DEBUG LOG END ------*/
1451 /* check all url service list */
1452 for (service_number = 0; service_number < URL_SERVICE_NUMBER - 1; ++service_number) {
1453 /* if pointer that does not point NULL exists ... */
1454 if (url_service_list[service_number] == NULL) {
1455 /* create a service at empty pointer */
1456 url_service_list[service_number] = (struct l7vs_url_service *) calloc(1, sizeof(struct l7vs_url_service));
1458 /*-------- DEBUG LOG --------*/
1459 if (url_protomod.get_log_level != NULL &&
1460 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1461 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,38, "calloc: addr=%p, size=%ld",
1462 url_service_list[service_number], (unsigned long int) sizeof(struct l7vs_url_service));
1464 /*------ DEBUG LOG END ------*/
1466 if (url_service_list[service_number] == NULL) {
1467 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,28, "Could not allocate memory.");
1468 goto create_service_out;
1470 return_value = url_service_list[service_number];
1471 goto create_service_out;
1475 /* all service list is full */
1476 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,150, "url service list is full.");
1479 /*-------- DEBUG LOG --------*/
1480 if (url_protomod.get_log_level != NULL &&
1481 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1482 char ssl_str[DEBUG_STR_LEN] = {0};
1483 l7vs_url_service_c_str(ssl_str, return_value);
1484 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,167,
1485 "out_function: struct l7vs_url_service* l7vs_protomod_url_create_service():"
1486 "return_value=&(%s)", ssl_str);
1488 /*------ DEBUG LOG END ------*/
1490 return return_value;
1494 * Create temporary url service.
1496 * @return url service struct when create a service. NULL when cannot create service.
1498 static struct l7vs_url_service *
1499 l7vs_protomod_url_create_temp_service()
1501 struct l7vs_url_service* return_value = NULL;
1503 /*-------- DEBUG LOG --------*/
1504 if (url_protomod.get_log_level != NULL &&
1505 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1506 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,168,
1507 "in_function: struct l7vs_url_service* l7vs_protomod_url_create_temp_service()");
1509 /*------ DEBUG LOG END ------*/
1511 /* if pointer that does not point NULL exists ... */
1512 if (url_service_list[URL_SERVICE_NUMBER - 1] != NULL) {
1513 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_PROTOCOL,151, "Temporary url service is being used by other process.");
1514 goto create_temp_service_out;
1517 /* create temp service */
1518 url_service_list[URL_SERVICE_NUMBER - 1] = (struct l7vs_url_service *) calloc(1, sizeof(struct l7vs_url_service));
1520 /*-------- DEBUG LOG --------*/
1521 if (url_protomod.get_log_level != NULL &&
1522 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_SYSTEM_MEMORY)) {
1523 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,39, "calloc: addr=%p, size=%ld",
1524 url_service_list[URL_SERVICE_NUMBER - 1], (unsigned long int) sizeof(struct l7vs_url_service));
1526 /*------ DEBUG LOG END ------*/
1528 if (url_service_list[URL_SERVICE_NUMBER - 1] == NULL) {
1529 PUT_LOG_ERROR(url_protomod, LOG_CAT_L7VSD_SYSTEM_MEMORY,29, "Could not allocate memory");
1530 goto create_temp_service_out;
1533 return_value = url_service_list[URL_SERVICE_NUMBER - 1];
1535 create_temp_service_out:
1536 /*-------- DEBUG LOG --------*/
1537 if (url_protomod.get_log_level != NULL &&
1538 LOG_LV_DEBUG == url_protomod.get_log_level(LOG_CAT_L7VSD_PROTOCOL)) {
1539 char ssl_str[DEBUG_STR_LEN] = {0};
1540 l7vs_url_service_c_str(ssl_str, return_value);
1541 PUT_LOG_DEBUG(url_protomod, LOG_CAT_L7VSD_PROTOCOL,169,
1542 "out_function: struct l7vs_url_service* l7vs_protomod_url_create_service():"
1543 "return_value=&(%s)", ssl_str);
1545 /*------ DEBUG LOG END ------*/
1547 return return_value;
1551 * Serialize struct l7vs_url_service for debug log.
1552 * @param[out] buf serialized string
1553 * @param[in] url l7vs_url_service struct
1555 static void l7vs_url_service_c_str(char* buf, struct l7vs_url_service* url) {
1557 snprintf(buf, DEBUG_STR_LEN, "NULL");
1560 snprintf(buf, DEBUG_STR_LEN, "service_handle=%d, pattern_match=\"%s\", uri_pattern_match=\"%s\", host_pattern_match=\"%s\", "
1561 "forwarded_for=%d, reschedule=%d", url->service_handle, url->pattern_match, url->uri_pattern_match, url->host_pattern_match,
1562 url->forwarded_for, url->reschedule);
1567 * Serialize struct l7vs_url_service_arg for debug log.
1568 * @param[out] buf serialized string
1569 * @param[in] url_arg l7vs_url_service_arg struct
1571 void l7vs_url_service_arg_c_str(char* buf, struct l7vs_url_service_arg* url_arg) {
1572 if (url_arg == NULL) {
1573 snprintf(buf, DEBUG_STR_LEN, "NULL");
1576 snprintf(buf, DEBUG_STR_LEN, "pattern_match=\"%s\", uri_pattern_match=\"%s\", host_pattern_match=\"%s\", forwarded_for=%d, reschedule=%d",
1577 url_arg->pattern_match, url_arg->uri_pattern_match, url_arg->host_pattern_match, url_arg->forwarded_for, url_arg->reschedule);