diff --git a/include/query_processor.h b/include/query_processor.h index cad2de7a2d..1e489371c9 100644 --- a/include/query_processor.h +++ b/include/query_processor.h @@ -14,6 +14,7 @@ struct _Query_Processor_rule_t { char *schemaname; int flagIN; char *client_addr; + int client_addr_wildcard_position; char *proxy_addr; int proxy_port; uint64_t digest; diff --git a/lib/ProxySQL_Admin.cpp b/lib/ProxySQL_Admin.cpp index 51db65dd71..0fb6925626 100644 --- a/lib/ProxySQL_Admin.cpp +++ b/lib/ProxySQL_Admin.cpp @@ -7070,6 +7070,22 @@ char * ProxySQL_Admin::load_mysql_query_rules_to_runtime() { QP_rule_t * nqpr; for (std::vector::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) { SQLite3_row *r=*it; + if (r->fields[4]) { + char *pct = NULL; + if (strlen(r->fields[4]) >= INET6_ADDRSTRLEN) { + proxy_error("Query rule with rule_id=%s has an invalid client_addr: %s\n", r->fields[0], r->fields[4]); + continue; + } + pct = strchr(r->fields[4],'%'); + if (pct) { // there is a wildcard + if (strlen(pct) == 1) { + // % is at the end of the string, good + } else { + proxy_error("Query rule with rule_id=%s has a wildcard that is not at the end of client_addr: %s\n", r->fields[0], r->fields[4]); + continue; + } + } + } nqpr=GloQPro->new_query_rule( atoi(r->fields[0]), // rule_id true, diff --git a/lib/Query_Processor.cpp b/lib/Query_Processor.cpp index f0407076a1..9c6865a74f 100644 --- a/lib/Query_Processor.cpp +++ b/lib/Query_Processor.cpp @@ -495,7 +495,23 @@ QP_rule_t * Query_Processor::new_query_rule(int rule_id, bool active, char *user newQR->regex_engine2=NULL; newQR->hits=0; + newQR->client_addr_wildcard_position = -1; // not existing by default newQR->client_addr=(client_addr ? strdup(client_addr) : NULL); + if (newQR->client_addr) { + char *pct = strchr(newQR->client_addr,'%'); + if (pct) { // there is a wildcard . We assume Admin did already all the input validation + if (pct == newQR->client_addr) { + // client_addr == '%' + // % is at the end of the string, but also at the beginning + // becoming a catch all + newQR->client_addr_wildcard_position = 0; + } else { + // this math is valid also if (pct == newQR->client_addr) + // but we separate it to clarify that client_addr_wildcard_position is a match all + newQR->client_addr_wildcard_position = strlen(newQR->client_addr) - strlen(pct); + } + } + } newQR->proxy_addr=(proxy_addr ? strdup(proxy_addr) : NULL); newQR->proxy_port=proxy_port; newQR->log=log; @@ -957,9 +973,19 @@ Query_Processor_Output * Query_Processor::process_mysql_query(MySQL_Session *ses // match on client address if (qr->client_addr && strlen(qr->client_addr)) { if (sess->client_myds->addr.addr) { - if (strcmp(qr->client_addr,sess->client_myds->addr.addr)!=0) { - proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id); - continue; + if (qr->client_addr_wildcard_position == -1) { // no wildcard , old algorithm + if (strcmp(qr->client_addr,sess->client_myds->addr.addr)!=0) { + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id); + continue; + } + } else if (qr->client_addr_wildcard_position==0) { + // catch all! + // therefore we have a match + } else { // client_addr_wildcard_position > 0 + if (strncmp(qr->client_addr,sess->client_myds->addr.addr,qr->client_addr_wildcard_position)!=0) { + proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id); + continue; + } } } }