nwfilter: move shared nwfilter driver functions into nwfilter_tech_driver.c

Introduce nwfilter_tech_driver.c which holds shared non driver specific
methods.
The following logic can be reused by new nwfilter drivers, which are not
ebiptables specific:
- data type print logic, used for constructing ascii cli arguments out
  of nwfilter data;
- chain jump proto type l3_proto_idx logic;
- virNWFilterRule sorting.

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Dion Bosschieter <dionbosschieter@gmail.com>
[DB: moved virstring.h include to source file & added to POTFILES]
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Dion Bosschieter authored and Daniel P. Berrangé committed 2026-02-12 12:49:25 +00:00
1 parent 6e101ad0c7
commit 8e377728c5
5 files changed
+302 -264

No files matched your search

+1
View File
@@ -162,6 +162,7 @@ src/nwfilter/nwfilter_driver.c
src/nwfilter/nwfilter_ebiptables_driver.c
src/nwfilter/nwfilter_gentech_driver.c
src/nwfilter/nwfilter_learnipaddr.c
src/nwfilter/nwfilter_tech_driver.c
src/openvz/openvz_conf.c
src/openvz/openvz_driver.c
src/openvz/openvz_util.c
+1
View File
@@ -1,6 +1,7 @@
nwfilter_driver_sources = [
'nwfilter_driver.c',
'nwfilter_gentech_driver.c',
'nwfilter_tech_driver.c',
'nwfilter_dhcpsnoop.c',
'nwfilter_ebiptables_driver.c',
'nwfilter_learnipaddr.c',
+1 -261
View File
@@ -34,6 +34,7 @@
#include "virerror.h"
#include "nwfilter_conf.h"
#include "nwfilter_ebiptables_driver.h"
#include "nwfilter_tech_driver.h"
#include "virfile.h"
#include "configmake.h"
#include "virstring.h"
@@ -82,25 +83,6 @@ static void ebiptablesDriverShutdown(void);
static int ebtablesCleanAll(const char *ifname);
static int ebiptablesAllTeardown(const char *ifname);
struct virNWFilterUShortMap {
unsigned short attr;
const char *val;
};
enum virNWFilterProtoIdx {
VIR_NWFILTER_PROTO_IDX_IPV4 = 0,
VIR_NWFILTER_PROTO_IDX_IPV6,
VIR_NWFILTER_PROTO_IDX_ARP,
VIR_NWFILTER_PROTO_IDX_RARP,
VIR_NWFILTER_PROTO_IDX_MAC,
VIR_NWFILTER_PROTO_IDX_VLAN,
VIR_NWFILTER_PROTO_IDX_STP,
VIR_NWFILTER_PROTO_IDX_LAST
};
#define virNWFilterUShortMapEntryIdx(IDX, ATT, VAL) [IDX] = { .attr = ATT, .val = VAL }
/* A lookup table for translating ethernet protocol IDs to human readable
* strings. None of the human readable strings must be found as a prefix
* in another entry here (example 'ab' would be found in 'abc') to allow
@@ -117,7 +99,6 @@ static const struct virNWFilterUShortMap l3_protocols[] = {
virNWFilterUShortMapEntryIdx(VIR_NWFILTER_PROTO_IDX_LAST, 0, NULL),
};
static char chainprefixes_host[3] = {
CHAINPREFIX_HOST_IN,
CHAINPREFIX_HOST_OUT,
@@ -136,12 +117,6 @@ typedef struct {
const char *targetChain;
} iptablesBaseChainFW;
typedef struct {
const char *ifname;
int nrules;
virNWFilterRuleInst **rules;
} virNWFilterChainCreateCallbackData;
static iptablesBaseChainFW fw_base_chains[] = {
{"FORWARD", "1", VIRT_IN_CHAIN},
{"FORWARD", "2", VIRT_OUT_CHAIN},
@@ -149,206 +124,6 @@ static iptablesBaseChainFW fw_base_chains[] = {
{"INPUT", "1", HOST_IN_CHAIN},
};
static int
virNWFilterPrintVar(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item,
bool *done)
{
*done = false;
if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
const char *val;
val = virNWFilterVarCombIterGetVarValue(vars, item->varAccess);
if (!val) {
/* error has been reported */
return -1;
}
if (virStrcpy(buf, val, bufsize) < 0) {
const char *varName;
varName = virNWFilterVarAccessGetVarName(item->varAccess);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Buffer too small to print variable '%1$s' into"),
varName);
return -1;
}
*done = true;
}
return 0;
}
static int
_virNWFilterPrintDataType(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item,
bool asHex, bool directionIn)
{
bool done;
g_autofree char *data = NULL;
uint8_t ctr;
g_auto(virBuffer) vb = VIR_BUFFER_INITIALIZER;
g_autofree char *flags = NULL;
if (virNWFilterPrintVar(vars, buf, bufsize, item, &done) < 0)
return -1;
if (done)
return 0;
switch (item->datatype) {
case DATATYPE_IPADDR:
data = virSocketAddrFormat(&item->u.ipaddr);
if (!data)
return -1;
if (g_snprintf(buf, bufsize, "%s", data) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("buffer too small for IP address"));
return -1;
}
break;
case DATATYPE_IPV6ADDR:
data = virSocketAddrFormat(&item->u.ipaddr);
if (!data)
return -1;
if (g_snprintf(buf, bufsize, "%s", data) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("buffer too small for IPv6 address"));
return -1;
}
break;
case DATATYPE_MACADDR:
case DATATYPE_MACMASK:
if (bufsize < VIR_MAC_STRING_BUFLEN) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for MAC address"));
return -1;
}
virMacAddrFormat(&item->u.macaddr, buf);
break;
case DATATYPE_IPV6MASK:
case DATATYPE_IPMASK:
if (g_snprintf(buf, bufsize, "%d",
item->u.u8) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint8 type"));
return -1;
}
break;
case DATATYPE_UINT32:
case DATATYPE_UINT32_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%u",
item->u.u32) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint32 type"));
return -1;
}
break;
case DATATYPE_UINT16:
case DATATYPE_UINT16_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%d",
item->u.u16) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint16 type"));
return -1;
}
break;
case DATATYPE_UINT8:
case DATATYPE_UINT8_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%d",
item->u.u8) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint8 type"));
return -1;
}
break;
case DATATYPE_IPSETNAME:
if (virStrcpy(buf, item->u.ipset.setname, bufsize) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer to small for ipset name"));
return -1;
}
break;
case DATATYPE_IPSETFLAGS:
for (ctr = 0; ctr < item->u.ipset.numFlags; ctr++) {
if (ctr != 0)
virBufferAddLit(&vb, ",");
if ((item->u.ipset.flags & (1 << ctr))) {
if (directionIn)
virBufferAddLit(&vb, "dst");
else
virBufferAddLit(&vb, "src");
} else {
if (directionIn)
virBufferAddLit(&vb, "src");
else
virBufferAddLit(&vb, "dst");
}
}
flags = virBufferContentAndReset(&vb);
if (virStrcpy(buf, flags, bufsize) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for IPSETFLAGS type"));
return -1;
}
break;
case DATATYPE_STRING:
case DATATYPE_STRINGCOPY:
case DATATYPE_BOOLEAN:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot print data type %1$x"), item->datatype);
return -1;
case DATATYPE_LAST:
default:
virReportEnumRangeError(virNWFilterAttrDataType, item->datatype);
return -1;
}
return 0;
}
static int
virNWFilterPrintDataType(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 0, 0);
}
static int
virNWFilterPrintDataTypeDirection(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item, bool directionIn)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 0, directionIn);
}
static int
virNWFilterPrintDataTypeAsHex(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 1, 0);
}
static int
ebtablesHandleEthHdr(virFirewall *fw,
@@ -3040,41 +2815,6 @@ ebtablesCleanAll(const char *ifname)
}
static int
virNWFilterRuleInstSort(const void *a, const void *b)
{
const virNWFilterRuleInst *insta = a;
const virNWFilterRuleInst *instb = b;
const char *root = virNWFilterChainSuffixTypeToString(
VIR_NWFILTER_CHAINSUFFIX_ROOT);
bool root_a = STREQ(insta->chainSuffix, root);
bool root_b = STREQ(instb->chainSuffix, root);
/* ensure root chain commands appear before all others since
we will need them to create the child chains */
if (root_a) {
if (!root_b)
return -1; /* a before b */
} else if (root_b) {
return 1; /* b before a */
}
/* priorities are limited to range [-1000, 1000] */
return insta->priority - instb->priority;
}
static int
virNWFilterRuleInstSortPtr(const void *a,
const void *b,
void *opaque G_GNUC_UNUSED)
{
virNWFilterRuleInst * const *insta = a;
virNWFilterRuleInst * const *instb = b;
return virNWFilterRuleInstSort(*insta, *instb);
}
static int
ebiptablesFilterOrderSort(const void *va,
const void *vb,
+251
View File
@@ -0,0 +1,251 @@
/*
* nwfilter_tech_driver.c: common/shared functions used in nwfilter gentech drivers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include "nwfilter_tech_driver.h"
#include "nwfilter_conf.h"
#include "virstring.h"
#define VIR_FROM_THIS VIR_FROM_NWFILTER
int virNWFilterRuleInstSort(const void *a, const void *b)
{
const virNWFilterRuleInst *insta = a;
const virNWFilterRuleInst *instb = b;
const char *root = virNWFilterChainSuffixTypeToString(
VIR_NWFILTER_CHAINSUFFIX_ROOT);
bool root_a = STREQ(insta->chainSuffix, root);
bool root_b = STREQ(instb->chainSuffix, root);
/* ensure root chain commands appear before all others since
we will need them to create the child chains */
if (root_a) {
if (!root_b)
return -1; /* a before b */
} else if (root_b) {
return 1; /* b before a */
}
/* priorities are limited to range [-1000, 1000] */
return insta->priority - instb->priority;
}
int virNWFilterRuleInstSortPtr(const void *a,
const void *b,
void *opaque G_GNUC_UNUSED)
{
virNWFilterRuleInst * const *insta = a;
virNWFilterRuleInst * const *instb = b;
return virNWFilterRuleInstSort(*insta, *instb);
}
int virNWFilterPrintVar(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item,
bool *done)
{
*done = false;
if ((item->flags & NWFILTER_ENTRY_ITEM_FLAG_HAS_VAR)) {
const char *val;
val = virNWFilterVarCombIterGetVarValue(vars, item->varAccess);
if (!val) {
/* error has been reported */
return -1;
}
if (virStrcpy(buf, val, bufsize) < 0) {
const char *varName;
varName = virNWFilterVarAccessGetVarName(item->varAccess);
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Buffer too small to print variable '%1$s' into"),
varName);
return -1;
}
*done = true;
}
return 0;
}
static int
_virNWFilterPrintDataType(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item,
bool asHex, bool directionIn)
{
bool done;
g_autofree char *data = NULL;
uint8_t ctr;
g_auto(virBuffer) vb = VIR_BUFFER_INITIALIZER;
g_autofree char *flags = NULL;
if (virNWFilterPrintVar(vars, buf, bufsize, item, &done) < 0)
return -1;
if (done)
return 0;
switch (item->datatype) {
case DATATYPE_IPADDR:
data = virSocketAddrFormat(&item->u.ipaddr);
if (!data)
return -1;
if (g_snprintf(buf, bufsize, "%s", data) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("buffer too small for IP address"));
return -1;
}
break;
case DATATYPE_IPV6ADDR:
data = virSocketAddrFormat(&item->u.ipaddr);
if (!data)
return -1;
if (g_snprintf(buf, bufsize, "%s", data) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("buffer too small for IPv6 address"));
return -1;
}
break;
case DATATYPE_MACADDR:
case DATATYPE_MACMASK:
if (bufsize < VIR_MAC_STRING_BUFLEN) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for MAC address"));
return -1;
}
virMacAddrFormat(&item->u.macaddr, buf);
break;
case DATATYPE_IPV6MASK:
case DATATYPE_IPMASK:
if (g_snprintf(buf, bufsize, "%d",
item->u.u8) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint8 type"));
return -1;
}
break;
case DATATYPE_UINT32:
case DATATYPE_UINT32_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%u",
item->u.u32) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint32 type"));
return -1;
}
break;
case DATATYPE_UINT16:
case DATATYPE_UINT16_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%d",
item->u.u16) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint16 type"));
return -1;
}
break;
case DATATYPE_UINT8:
case DATATYPE_UINT8_HEX:
if (g_snprintf(buf, bufsize, asHex ? "0x%x" : "%d",
item->u.u8) >= bufsize) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for uint8 type"));
return -1;
}
break;
case DATATYPE_IPSETNAME:
if (virStrcpy(buf, item->u.ipset.setname, bufsize) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer to small for ipset name"));
return -1;
}
break;
case DATATYPE_IPSETFLAGS:
for (ctr = 0; ctr < item->u.ipset.numFlags; ctr++) {
if (ctr != 0)
virBufferAddLit(&vb, ",");
if ((item->u.ipset.flags & (1 << ctr))) {
if (directionIn)
virBufferAddLit(&vb, "dst");
else
virBufferAddLit(&vb, "src");
} else {
if (directionIn)
virBufferAddLit(&vb, "src");
else
virBufferAddLit(&vb, "dst");
}
}
flags = virBufferContentAndReset(&vb);
if (virStrcpy(buf, flags, bufsize) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Buffer too small for IPSETFLAGS type"));
return -1;
}
break;
case DATATYPE_STRING:
case DATATYPE_STRINGCOPY:
case DATATYPE_BOOLEAN:
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Cannot print data type %1$x"), item->datatype);
return -1;
case DATATYPE_LAST:
default:
virReportEnumRangeError(virNWFilterAttrDataType, item->datatype);
return -1;
}
return 0;
}
int virNWFilterPrintDataType(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 0, 0);
}
int virNWFilterPrintDataTypeDirection(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item, bool directionIn)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 0, directionIn);
}
int virNWFilterPrintDataTypeAsHex(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item)
{
return _virNWFilterPrintDataType(vars, buf, bufsize, item, 1, 0);
}
+48 -3
View File
@@ -25,9 +25,6 @@
#include "virnwfilterobj.h"
typedef struct _virNWFilterTechDriver virNWFilterTechDriver;
typedef struct _virNWFilterRuleInst virNWFilterRuleInst;
struct _virNWFilterRuleInst {
const char *chainSuffix;
@@ -38,6 +35,31 @@ struct _virNWFilterRuleInst {
};
typedef struct _virNWFilterChainCreateCallbackData virNWFilterChainCreateCallbackData;
struct _virNWFilterChainCreateCallbackData {
const char *ifname;
int nrules;
virNWFilterRuleInst **rules;
};
struct virNWFilterUShortMap {
unsigned short attr;
const char *val;
};
enum virNWFilterProtoIdx {
VIR_NWFILTER_PROTO_IDX_IPV4 = 0,
VIR_NWFILTER_PROTO_IDX_IPV6,
VIR_NWFILTER_PROTO_IDX_ARP,
VIR_NWFILTER_PROTO_IDX_RARP,
VIR_NWFILTER_PROTO_IDX_MAC,
VIR_NWFILTER_PROTO_IDX_VLAN,
VIR_NWFILTER_PROTO_IDX_STP,
VIR_NWFILTER_PROTO_IDX_LAST
};
#define virNWFilterUShortMapEntryIdx(IDX, ATT, VAL) [IDX] = { .attr = ATT, .val = VAL }
typedef int (*virNWFilterTechDrvInit)(bool privileged);
typedef void (*virNWFilterTechDrvShutdown)(void);
@@ -69,6 +91,7 @@ enum techDrvFlags {
TECHDRV_FLAG_INITIALIZED = (1 << 0),
};
typedef struct _virNWFilterTechDriver virNWFilterTechDriver;
struct _virNWFilterTechDriver {
const char *name;
enum techDrvFlags flags;
@@ -87,3 +110,25 @@ struct _virNWFilterTechDriver {
virNWFilterDropAllRules applyDropAllRules;
virNWFilterRemoveBasicRules removeBasicRules;
};
int virNWFilterRuleInstSort(const void *a, const void *b);
int virNWFilterRuleInstSortPtr(const void *a,
const void *b,
void *opaque);
int virNWFilterPrintVar(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item,
bool *done);
int virNWFilterPrintDataType(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item);
int virNWFilterPrintDataTypeDirection(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item, bool directionIn);
int virNWFilterPrintDataTypeAsHex(virNWFilterVarCombIter *vars,
char *buf, int bufsize,
nwItemDesc *item);