blob: 50c8d44b8f31f8e87966375edf4eb13883ca7354 [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*****************************************************************************
*
* IPAllow.cc - Implementation to IP Access Control systtem
*
*
****************************************************************************/
#include "libts.h"
#include "Main.h"
#include "IPAllow.h"
#include "ProxyConfig.h"
#include "StatSystem.h"
#include "P_EventSystem.h"
#include "P_Cache.h"
#define IPAllowRegisterConfigUpdateFunc REC_RegisterConfigUpdateFunc
#define IPAllowReadConfigStringAlloc REC_ReadConfigStringAlloc
IpAllow *ip_allow_table = NULL;
Ptr<ProxyMutex> ip_reconfig_mutex;
//
// struct IPAllow_FreerContinuation
// Continuation to free old cache control lists after
// a timeout
//
struct IPAllow_FreerContinuation;
typedef int (IPAllow_FreerContinuation::*IPAllow_FrContHandler) (int, void *);
struct IPAllow_FreerContinuation: public Continuation
{
IpAllow *p;
int freeEvent(int event, Event * e)
{
NOWARN_UNUSED(event);
NOWARN_UNUSED(e);
Debug("ip-allow", "Deleting old table");
delete p;
delete this;
return EVENT_DONE;
}
IPAllow_FreerContinuation(IpAllow * ap):Continuation(NULL), p(ap)
{
SET_HANDLER((IPAllow_FrContHandler) & IPAllow_FreerContinuation::freeEvent);
}
};
// struct IPAllow_UpdateContinuation
//
// Used to read the ip_allow.conf file after the manager signals
// a change
//
struct IPAllow_UpdateContinuation: public Continuation
{
int file_update_handler(int etype, void *data)
{
NOWARN_UNUSED(etype);
NOWARN_UNUSED(data);
reloadIPAllow();
delete this;
return EVENT_DONE;
}
IPAllow_UpdateContinuation(ProxyMutex * m):Continuation(m)
{
SET_HANDLER(&IPAllow_UpdateContinuation::file_update_handler);
}
};
int
ipAllowFile_CB(const char *name, RecDataT data_type, RecData data, void *cookie)
{
NOWARN_UNUSED(name);
NOWARN_UNUSED(data_type);
NOWARN_UNUSED(data);
NOWARN_UNUSED(cookie);
eventProcessor.schedule_imm(NEW(new IPAllow_UpdateContinuation(ip_reconfig_mutex)), ET_CACHE);
return 0;
}
//
// Begin API functions
//
void
initIPAllow()
{
// Should not have been initialized before
ink_assert(ip_allow_table == NULL);
ip_reconfig_mutex = new_ProxyMutex();
ip_allow_table = NEW(new IpAllow("proxy.config.cache.ip_allow.filename", "IpAllow", "ip_allow"));
ip_allow_table->BuildTable();
IPAllowRegisterConfigUpdateFunc("proxy.config.cache.ip_allow.filename", ipAllowFile_CB, NULL);
}
void
reloadIPAllow()
{
IpAllow *new_table;
Debug("ip_allow", "ip_allow.config updated, reloading");
// Schedule the current table for deallocation in the future
eventProcessor.schedule_in(NEW(new IPAllow_FreerContinuation(ip_allow_table)), IP_ALLOW_TIMEOUT, ET_CACHE);
new_table = NEW(new IpAllow("proxy.config.cache.ip_allow.filename", "IpAllow", "ip_allow"));
new_table->BuildTable();
ink_atomic_swap_ptr(&ip_allow_table, new_table);
}
//
// End API functions
//
IpAllow::IpAllow(const char *config_var, const char *name, const char *action_val):
IpLookup(name),
config_file_var(config_var),
module_name(name),
action(action_val),
err_allow_all(false)
{
char *config_file;
config_file_var = xstrdup(config_var);
config_file_path[0] = '\0';
IPAllowReadConfigStringAlloc(config_file, (char *) config_file_var);
ink_release_assert(config_file != NULL);
ink_filepath_make(config_file_path, sizeof(config_file_path), system_config_directory, config_file);
xfree(config_file);
}
IpAllow::~IpAllow()
{
}
void
IpAllow::Print()
{
printf("IpAllow Table with %d entries\n", num_el);
if (err_allow_all == true) {
printf("\t err_allow_all is true\n");
}
IpLookup::Print();
}
int
IpAllow::BuildTable()
{
char *tok_state = NULL;
char *line = NULL;
const char *errPtr = NULL;
char errBuf[1024];
char *file_buf = NULL;
int line_num = 0;
ip_addr_t addr1 = 0;
ip_addr_t addr2 = 0;
matcher_line line_info;
bool alarmAlready = false;
// Table should be empty
ink_assert(num_el == 0);
file_buf = readIntoBuffer(config_file_path, module_name, NULL);
if (file_buf == NULL) {
err_allow_all = false;
Warning("%s Failed to read %s. All IP Addresses will be blocked", module_name, config_file_path);
return 1;
}
line = tokLine(file_buf, &tok_state);
while (line != NULL) {
line_num++;
// skip all blank spaces at beginning of line
while (*line && isspace(*line)) {
line++;
}
if (*line != '\0' && *line != '#') {
errPtr = parseConfigLine(line, &line_info, &ip_allow_tags);
if (errPtr != NULL) {
snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry at line %d : %s",
module_name, config_file_path, line_num, errPtr);
SignalError(errBuf, alarmAlready);
} else {
ink_assert(line_info.type == MATCH_IP);
errPtr = ExtractIpRange(line_info.line[1][line_info.dest_entry], &addr1, &addr2);
if (errPtr != NULL) {
snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry at line %d : %s",
module_name, config_file_path, line_num, errPtr);
SignalError(errBuf, alarmAlready);
} else {
// INKqa05845
// Search for "action=ip_allow" or "action=ip_deny".
char *label, *val;
IpAllowRecord *rec;
for (int i = 0; i < MATCHER_MAX_TOKENS; i++) {
label = line_info.line[0][i];
val = line_info.line[1][i];
if (label == NULL)
continue;
if (strcasecmp(label, "action") == 0) {
if (strcasecmp(val, "ip_allow") == 0) {
rec = (IpAllowRecord *) xmalloc(sizeof(IpAllowRecord));
rec->access = IP_ALLOW;
rec->line_num = line_num;
this->NewEntry(addr1, addr2, (void *) rec);
} else if (strcasecmp(val, "ip_deny") == 0) {
rec = (IpAllowRecord *) xmalloc(sizeof(IpAllowRecord));
rec->access = IP_DENY;
rec->line_num = line_num;
this->NewEntry(addr1, addr2, (void *) rec);
} else {
snprintf(errBuf, sizeof(errBuf), "%s discarding %s entry at line %d : %s", module_name, config_file_path, line_num, "Invalid action specified"); //changed by YTS Team, yamsat bug id -59022
SignalError(errBuf, alarmAlready);
}
}
}
// this->NewEntry(addr1, addr2, NULL);
}
}
}
line = tokLine(NULL, &tok_state);
}
if (num_el == 0) {
Warning("%s No entries in %s. All IP Addresses will be blocked", module_name, config_file_path);
err_allow_all = false;
}
if (is_debug_tag_set("ip-allow")) {
Print();
}
xfree(file_buf);
return 0;
}