Driver: Drop limited traffic.

This commit is contained in:
Nodir Temirkhodjaev 2018-01-05 13:51:34 +05:00
parent bb954c116b
commit 01311d12aa
4 changed files with 130 additions and 58 deletions

View File

@ -158,6 +158,29 @@ fort_conf_ref_flags_set (const PFORT_CONF_FLAGS conf_flags)
return old_conf_flags; return old_conf_flags;
} }
static void
fort_callout_classify_block (FWPS_CLASSIFY_OUT0 *classifyOut)
{
classifyOut->actionType = FWP_ACTION_BLOCK;
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
static void
fort_callout_classify_permit (const FWPS_FILTER0 *filter,
FWPS_CLASSIFY_OUT0 *classifyOut)
{
classifyOut->actionType = FWP_ACTION_PERMIT;
if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) {
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
}
static void
fort_callout_classify_continue (FWPS_CLASSIFY_OUT0 *classifyOut)
{
classifyOut->actionType = FWP_ACTION_CONTINUE;
}
static void static void
fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
@ -181,25 +204,26 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
conf_ref = fort_conf_ref_take(); conf_ref = fort_conf_ref_take();
if (conf_ref == NULL) { if (conf_ref == NULL) {
if (g_device->prov_boot) if (g_device->prov_boot) {
goto block; fort_callout_classify_block(classifyOut);
} else {
classifyOut->actionType = FWP_ACTION_CONTINUE; fort_callout_classify_continue(classifyOut);
}
return; return;
} }
conf_flags = conf_ref->conf.flags; conf_flags = conf_ref->conf.flags;
if (conf_flags.stop_traffic) {
goto block;
}
flags = inFixedValues->incomingValue[flagsField].value.uint32; flags = inFixedValues->incomingValue[flagsField].value.uint32;
remote_ip = inFixedValues->incomingValue[remoteIpField].value.uint32; remote_ip = inFixedValues->incomingValue[remoteIpField].value.uint32;
if (!conf_flags.filter_enabled || conf_flags.stop_traffic if (!conf_flags.filter_enabled
|| (flags & FWP_CONDITION_FLAG_IS_LOOPBACK) || (flags & FWP_CONDITION_FLAG_IS_LOOPBACK)
|| remote_ip == 0xFFFFFFFF) { // Local broadcast || remote_ip == 0xFFFFFFFF) { // Local broadcast
fort_conf_ref_put(conf_ref);
if (conf_flags.stop_traffic) {
goto block;
}
goto permit; goto permit;
} }
@ -212,8 +236,6 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
&& ((app_index = fort_conf_app_index(&conf_ref->conf, path_len, path)), && ((app_index = fort_conf_app_index(&conf_ref->conf, path_len, path)),
fort_conf_app_blocked(&conf_ref->conf, app_index)); fort_conf_app_blocked(&conf_ref->conf, app_index));
fort_conf_ref_put(conf_ref);
if (!blocked) { if (!blocked) {
if (ip_included && conf_flags.log_stat) { if (ip_included && conf_flags.log_stat) {
const IPPROTO ip_proto = (IPPROTO) inFixedValues->incomingValue[ const IPPROTO ip_proto = (IPPROTO) inFixedValues->incomingValue[
@ -246,17 +268,15 @@ fort_callout_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
} }
block: block:
classifyOut->actionType = FWP_ACTION_BLOCK; fort_callout_classify_block(classifyOut);
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
goto end; goto end;
permit: permit:
classifyOut->actionType = FWP_ACTION_PERMIT; fort_callout_classify_permit(filter, classifyOut);
if ((filter->flags & FWPS_FILTER_FLAG_CLEAR_ACTION_RIGHT)) {
classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
}
end: end:
fort_conf_ref_put(conf_ref);
if (irp != NULL) { if (irp != NULL) {
fort_request_complete_info(irp, STATUS_SUCCESS, info); fort_request_complete_info(irp, STATUS_SUCCESS, info);
} }
@ -312,6 +332,22 @@ fort_callout_flow_delete_v4 (UINT16 layerId,
fort_stat_flow_delete(&g_device->stat, flowContext); fort_stat_flow_delete(&g_device->stat, flowContext);
} }
static void
fort_callout_flow_classify_v4 (const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
UINT64 flowContext,
FWPS_CLASSIFY_OUT0 *classifyOut,
UINT32 dataSize, BOOL inbound)
{
const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0;
if (fort_stat_flow_classify(&g_device->stat, flowContext,
headerSize + dataSize, inbound)) {
fort_callout_classify_block(classifyOut);
} else {
fort_callout_classify_continue(classifyOut);
}
}
static void static void
fort_callout_stream_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues, fort_callout_stream_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues, const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
@ -325,12 +361,11 @@ fort_callout_stream_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
const BOOL inbound = (streamData->flags & FWPS_STREAM_FLAG_RECEIVE) != 0; const BOOL inbound = (streamData->flags & FWPS_STREAM_FLAG_RECEIVE) != 0;
const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0; UNUSED(inFixedValues);
UNUSED(filter);
fort_stat_flow_classify(&g_device->stat, flowContext, fort_callout_flow_classify_v4(inMetaValues, flowContext, classifyOut,
headerSize + dataSize, inbound); dataSize, inbound);
classifyOut->actionType = FWP_ACTION_CONTINUE;
} }
static void static void
@ -348,12 +383,11 @@ fort_callout_datagram_classify_v4 (const FWPS_INCOMING_VALUES0 *inFixedValues,
FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint8; FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].value.uint8;
const BOOL inbound = (direction == FWP_DIRECTION_INBOUND); const BOOL inbound = (direction == FWP_DIRECTION_INBOUND);
const UINT32 headerSize = inbound ? inMetaValues->transportHeaderSize : 0; UNUSED(inFixedValues);
UNUSED(filter);
fort_stat_flow_classify(&g_device->stat, flowContext, fort_callout_flow_classify_v4(inMetaValues, flowContext, classifyOut,
headerSize + dataSize, inbound); dataSize, inbound);
classifyOut->actionType = FWP_ACTION_CONTINUE;
} }
static void static void

View File

@ -319,10 +319,19 @@ fort_stat_flow_remove_context (UINT64 flow_id, UINT16 layer_id,
static void static void
fort_stat_flow_transport_set_contexts (PFORT_STAT stat, UINT64 flow_id, fort_stat_flow_transport_set_contexts (PFORT_STAT stat, UINT64 flow_id,
UINT64 flow_context, UINT64 flow_context, BOOL is_udp,
BOOL is_udp, BOOL speed_limit) BOOL speed_limit, BOOL is_reauth)
{ {
if (!is_udp && speed_limit) { if (is_udp) return;
if (is_reauth) {
fort_stat_flow_remove_context(flow_id,
FWPS_LAYER_INBOUND_TRANSPORT_V4, stat->in_transport4_id);
fort_stat_flow_remove_context(flow_id,
FWPS_LAYER_OUTBOUND_TRANSPORT_V4, stat->out_transport4_id);
}
if (speed_limit) {
fort_stat_flow_set_context(flow_id, FWPS_LAYER_INBOUND_TRANSPORT_V4, fort_stat_flow_set_context(flow_id, FWPS_LAYER_INBOUND_TRANSPORT_V4,
stat->in_transport4_id, flow_context); stat->in_transport4_id, flow_context);
fort_stat_flow_set_context(flow_id, FWPS_LAYER_OUTBOUND_TRANSPORT_V4, fort_stat_flow_set_context(flow_id, FWPS_LAYER_OUTBOUND_TRANSPORT_V4,
@ -438,8 +447,15 @@ fort_stat_update_limits (PFORT_STAT stat, PFORT_CONF_IO conf_io)
KLOCK_QUEUE_HANDLE lock_queue; KLOCK_QUEUE_HANDLE lock_queue;
KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue); KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue);
stat->limit_bits = conf_io->limit_bits; {
RtlCopyMemory(stat->limits, conf_io->limits, sizeof(stat->limits)); const UINT16 limit_bits = conf_io->limit_bits;
stat->limit_bits = limit_bits;
if (limit_bits != 0) {
RtlCopyMemory(stat->limits, conf_io->limits, sizeof(stat->limits));
}
}
KeReleaseInStackQueuedSpinLock(&lock_queue); KeReleaseInStackQueuedSpinLock(&lock_queue);
} }
@ -503,7 +519,7 @@ fort_stat_flow_associate (PFORT_STAT stat, UINT64 flow_id,
if (NT_SUCCESS(status)) { if (NT_SUCCESS(status)) {
// Set stream transport layer contexts // Set stream transport layer contexts
fort_stat_flow_transport_set_contexts( fort_stat_flow_transport_set_contexts(
stat, flow_id, flow_context, is_udp, speed_limit); stat, flow_id, flow_context, is_udp, speed_limit, is_reauth);
fort_stat_proc_inc(stat, proc_index); fort_stat_proc_inc(stat, proc_index);
} else { } else {
@ -547,7 +563,7 @@ fort_stat_flow_delete (PFORT_STAT stat, UINT64 flow_context)
KeReleaseInStackQueuedSpinLock(&lock_queue); KeReleaseInStackQueuedSpinLock(&lock_queue);
} }
static void static BOOL
fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context, fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context,
UINT32 data_len, BOOL inbound) UINT32 data_len, BOOL inbound)
{ {
@ -555,35 +571,44 @@ fort_stat_flow_classify (PFORT_STAT stat, UINT64 flow_context,
const UINT16 proc_index = (UINT16) (flow_context >> 48); const UINT16 proc_index = (UINT16) (flow_context >> 48);
const UCHAR group_index = (UCHAR) (flow_context >> 40); const UCHAR group_index = (UCHAR) (flow_context >> 40);
const UCHAR stat_version = (UCHAR) (flow_context >> 32); const UCHAR stat_version = (UCHAR) (flow_context >> 32);
BOOL limited = FALSE;
if (stat->closing) if (stat->closing)
return; return FALSE;
KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue); KeAcquireInStackQueuedSpinLock(&stat->lock, &lock_queue);
if (stat_version == stat->version) { if (stat_version == stat->version) {
PFORT_STAT_PROC proc = &stat->procs[proc_index]; PFORT_STAT_PROC proc = &stat->procs[proc_index];
UINT32 *proc_bytes = inbound ? &proc->traf.in_bytes
: &proc->traf.out_bytes;
// Add traffic to process // Add traffic to process
if (inbound) { *proc_bytes += data_len;
proc->traf.in_bytes += data_len;
} else {
proc->traf.out_bytes += data_len;
}
if (fort_stat_group_speed_limit(stat, group_index)) { if (fort_stat_group_speed_limit(stat, group_index)) {
PFORT_STAT_GROUP group = &stat->groups[group_index]; const PFORT_CONF_LIMIT group_limit = &stat->limits[group_index];
const UINT32 limit_bytes = inbound ? group_limit->in_bytes
: group_limit->out_bytes;
// Add traffic to app. group if (limit_bytes != 0) {
if (inbound) { PFORT_STAT_GROUP group = &stat->groups[group_index];
group->traf.in_bytes += data_len; UINT32 *group_bytes = inbound ? &group->traf.in_bytes
} else { : &group->traf.out_bytes;
group->traf.out_bytes += data_len;
if (*group_bytes < limit_bytes) {
// Add traffic to app. group
*group_bytes += data_len;
} else {
limited = TRUE;
}
} }
} }
stat->is_dirty = TRUE; stat->is_dirty = TRUE;
} }
KeReleaseInStackQueuedSpinLock(&lock_queue); KeReleaseInStackQueuedSpinLock(&lock_queue);
return limited;
} }
static void static void
@ -604,6 +629,7 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out)
const UINT32 proc_bits_len = FORT_LOG_STAT_PROC_SIZE(stat->proc_count); const UINT32 proc_bits_len = FORT_LOG_STAT_PROC_SIZE(stat->proc_count);
PFORT_STAT_TRAF out_traf = (PFORT_STAT_TRAF) (out + proc_bits_len); PFORT_STAT_TRAF out_traf = (PFORT_STAT_TRAF) (out + proc_bits_len);
PUCHAR out_proc_bits = (PUCHAR) out; PUCHAR out_proc_bits = (PUCHAR) out;
UINT16 i;
PFORT_STAT_PROC prev_proc = NULL; PFORT_STAT_PROC prev_proc = NULL;
UINT16 proc_index = stat->proc_head_index; UINT16 proc_index = stat->proc_head_index;
@ -611,7 +637,7 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out)
/* Mark processes as active to start */ /* Mark processes as active to start */
memset(out_proc_bits, 0xFF, proc_bits_len); memset(out_proc_bits, 0xFF, proc_bits_len);
for (UINT16 i = 0; proc_index != FORT_PROC_BAD_INDEX; ++i) { for (i = 0; proc_index != FORT_PROC_BAD_INDEX; ++i) {
PFORT_STAT_PROC proc = &stat->procs[proc_index]; PFORT_STAT_PROC proc = &stat->procs[proc_index];
const UINT16 next_index = proc->next_index; const UINT16 next_index = proc->next_index;
@ -633,5 +659,18 @@ fort_stat_dpc_traf_flush (PFORT_STAT stat, PCHAR out)
proc_index = next_index; proc_index = next_index;
} }
if (stat->limit_bits) {
PFORT_STAT_GROUP group = stat->groups;
UINT16 limit_bits = stat->limit_bits;
for (; limit_bits != 0; ++group) {
if (limit_bits & 1) {
group->traf_all.QuadPart = 0;
}
limit_bits >>= 1;
}
}
stat->is_dirty = FALSE; stat->is_dirty = FALSE;
} }

View File

@ -51,7 +51,7 @@ int ConfUtil::write(const FirewallConf &conf, QByteArray &buf)
int appPathsLen = 0; int appPathsLen = 0;
QStringList appPaths; QStringList appPaths;
appperms_arr_t appPerms; appperms_arr_t appPerms;
appgroups_arr_t appGroupIndexes; appgroups_map_t appGroupIndexes;
if (!parseAppGroups(conf.appGroupsList(), if (!parseAppGroups(conf.appGroupsList(),
appPaths, appPathsLen, appPaths, appPathsLen,
@ -110,7 +110,7 @@ bool ConfUtil::parseAppGroups(const QList<AppGroup *> &appGroups,
QStringList &appPaths, QStringList &appPaths,
int &appPathsLen, int &appPathsLen,
appperms_arr_t &appPerms, appperms_arr_t &appPerms,
appgroups_arr_t &appGroupIndexes) appgroups_map_t &appGroupIndexes)
{ {
const int groupsCount = appGroups.size(); const int groupsCount = appGroups.size();
if (groupsCount > APP_GROUP_MAX) { if (groupsCount > APP_GROUP_MAX) {
@ -159,7 +159,7 @@ bool ConfUtil::parseAppGroups(const QList<AppGroup *> &appGroups,
bool ConfUtil::parseApps(const QString &text, bool blocked, bool ConfUtil::parseApps(const QString &text, bool blocked,
appperms_map_t &appPermsMap, appperms_map_t &appPermsMap,
appgroups_arr_t &appGroupIndexes, appgroups_map_t &appGroupIndexes,
int groupOffset) int groupOffset)
{ {
foreach (const QStringRef &line, foreach (const QStringRef &line,
@ -184,7 +184,7 @@ bool ConfUtil::parseApps(const QString &text, bool blocked,
if (appPermsMap.contains(appPath)) { if (appPermsMap.contains(appPath)) {
appPerms |= appPermsMap.value(appPath); appPerms |= appPermsMap.value(appPath);
} else { } else {
appGroupIndexes.append(groupOffset); appGroupIndexes.insert(appPath, groupOffset);
} }
appPermsMap.insert(appPath, appPerms); appPermsMap.insert(appPath, appPerms);
@ -215,7 +215,7 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf,
const Ip4Range &incRange, const Ip4Range &excRange, const Ip4Range &incRange, const Ip4Range &excRange,
const QStringList &appPaths, const QStringList &appPaths,
const appperms_arr_t &appPerms, const appperms_arr_t &appPerms,
const appgroups_arr_t &appGroupIndexes) const appgroups_map_t &appGroupIndexes)
{ {
PFORT_CONF_IO drvConfIo = (PFORT_CONF_IO) output; PFORT_CONF_IO drvConfIo = (PFORT_CONF_IO) output;
PFORT_CONF drvConf = &drvConfIo->conf; PFORT_CONF drvConf = &drvConfIo->conf;
@ -241,7 +241,7 @@ void ConfUtil::writeData(char *output, const FirewallConf &conf,
writeNumbers(&data, excRange.toArray()); writeNumbers(&data, excRange.toArray());
appGroupsOff = CONF_DATA_OFFSET; appGroupsOff = CONF_DATA_OFFSET;
writeChars(&data, appGroupIndexes); writeChars(&data, appGroupIndexes.values().toVector());
appPermsOff = CONF_DATA_OFFSET; appPermsOff = CONF_DATA_OFFSET;
writeNumbers(&data, appPerms); writeNumbers(&data, appPerms);

View File

@ -1,7 +1,6 @@
#ifndef CONFUTIL_H #ifndef CONFUTIL_H
#define CONFUTIL_H #define CONFUTIL_H
#include <QObject>
#include <QByteArray> #include <QByteArray>
#include <QList> #include <QList>
#include <QMap> #include <QMap>
@ -15,7 +14,7 @@ QT_FORWARD_DECLARE_STRUCT(fort_conf_limit)
typedef QMap<QString, quint32> appperms_map_t; typedef QMap<QString, quint32> appperms_map_t;
typedef QVector<quint32> appperms_arr_t; typedef QVector<quint32> appperms_arr_t;
typedef QVector<qint8> appgroups_arr_t; typedef QMap<QString, qint8> appgroups_map_t;
class ConfUtil : public QObject class ConfUtil : public QObject
{ {
@ -42,11 +41,11 @@ private:
QStringList &appPaths, QStringList &appPaths,
int &appPathsLen, int &appPathsLen,
appperms_arr_t &appPerms, appperms_arr_t &appPerms,
appgroups_arr_t &appGroupIndexes); appgroups_map_t &appGroupIndexes);
bool parseApps(const QString &text, bool blocked, bool parseApps(const QString &text, bool blocked,
appperms_map_t &appPermsMap, appperms_map_t &appPermsMap,
appgroups_arr_t &appGroupIndexes, appgroups_map_t &appGroupIndexes,
int groupOffset); int groupOffset);
static QString parseAppPath(const QStringRef &line); static QString parseAppPath(const QStringRef &line);
@ -55,7 +54,7 @@ private:
const Ip4Range &incRange, const Ip4Range &excRange, const Ip4Range &incRange, const Ip4Range &excRange,
const QStringList &appPaths, const QStringList &appPaths,
const appperms_arr_t &appPerms, const appperms_arr_t &appPerms,
const appgroups_arr_t &appGroupIndexes); const appgroups_map_t &appGroupIndexes);
static quint16 writeLimits(struct fort_conf_limit *limits, static quint16 writeLimits(struct fort_conf_limit *limits,
const QList<AppGroup *> &appGroups); const QList<AppGroup *> &appGroups);