Extensions for iptables rules

This patch adds support for L3/L4 filtering using iptables. This adds
support for 'tcp', 'udp', 'icmp', 'igmp', 'sctp' etc. filtering.

As mentioned in the introduction, a .c file provided by this patch
is #include'd into a .c file. This will need work, but should be alright
for review.

Signed-off-by: Stefan Berger <stefanb@us.ibm.com>
This commit is contained in:
Stefan Berger 2010-03-25 13:46:12 -04:00 committed by Daniel P. Berrange
parent f85208eec6
commit 1130085cf0
6 changed files with 1472 additions and 11 deletions

View File

@ -303,6 +303,13 @@ AC_DEFINE_UNQUOTED([IPTABLES_PATH], "$IPTABLES_PATH", [path to iptables binary])
AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH]) AC_PATH_PROG([EBTABLES_PATH], [ebtables], /sbin/ebtables, [/usr/sbin:$PATH])
AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary]) AC_DEFINE_UNQUOTED([EBTABLES_PATH], "$EBTABLES_PATH", [path to ebtables binary])
AC_PATH_PROG([GREP_PATH], [grep], /bin/grep, [/bin:$PATH])
AC_DEFINE_UNQUOTED([GREP_PATH], "$GREP_PATH", [path to grep binary])
AC_PATH_PROG([GAWK_PATH], [gawk], /bin/gawk, [/bin:$PATH])
AC_DEFINE_UNQUOTED([GAWK_PATH], "$GAWK_PATH", [path to gawk binary])
if test "$with_openvz" = "yes"; then if test "$with_openvz" = "yes"; then
AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled]) AC_DEFINE_UNQUOTED([WITH_OPENVZ], 1, [whether OpenVZ driver is enabled])
fi fi

View File

@ -76,6 +76,19 @@ VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST,
"ipv4", "ipv4",
"ipv6"); "ipv6");
VIR_ENUM_IMPL(virNWFilterRuleProtocol, VIR_NWFILTER_RULE_PROTOCOL_LAST,
"none",
"mac",
"arp",
"ip",
"ipv6",
"tcp",
"icmp",
"igmp",
"udp",
"sctp",
"all");
/* /*
* a map entry for a simple static int-to-string map * a map entry for a simple static int-to-string map
@ -117,6 +130,10 @@ static const char srcipaddr_str[] = "srcipaddr";
static const char srcipmask_str[] = "srcipmask"; static const char srcipmask_str[] = "srcipmask";
static const char dstipaddr_str[] = "dstipaddr"; static const char dstipaddr_str[] = "dstipaddr";
static const char dstipmask_str[] = "dstipmask"; static const char dstipmask_str[] = "dstipmask";
static const char srcipfrom_str[] = "srcipfrom";
static const char srcipto_str[] = "srcipto";
static const char dstipfrom_str[] = "dstipfrom";
static const char dstipto_str[] = "dstipto";
static const char srcportstart_str[] = "srcportstart"; static const char srcportstart_str[] = "srcportstart";
static const char srcportend_str[] = "srcportend"; static const char srcportend_str[] = "srcportend";
static const char dstportstart_str[] = "dstportstart"; static const char dstportstart_str[] = "dstportstart";
@ -135,6 +152,10 @@ static const char dscp_str[] = "dscp";
#define SRCIPMASK srcipmask_str #define SRCIPMASK srcipmask_str
#define DSTIPADDR dstipaddr_str #define DSTIPADDR dstipaddr_str
#define DSTIPMASK dstipmask_str #define DSTIPMASK dstipmask_str
#define SRCIPFROM srcipfrom_str
#define SRCIPTO srcipto_str
#define DSTIPFROM dstipfrom_str
#define DSTIPTO dstipto_str
#define SRCPORTSTART srcportstart_str #define SRCPORTSTART srcportstart_str
#define SRCPORTEND srcportend_str #define SRCPORTEND srcportend_str
#define DSTPORTSTART dstportstart_str #define DSTPORTSTART dstportstart_str
@ -831,6 +852,149 @@ static const virXMLAttr2Struct ipv6Attributes[] = {
}; };
#define COMMON_L3_MAC_PROPS(STRUCT) \
{\
.name = SRCMACADDR,\
.datatype = DATATYPE_MACADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.dataSrcMACAddr),\
}
#define COMMON_IP_PROPS(STRUCT) \
COMMON_L3_MAC_PROPS(STRUCT),\
{\
.name = SRCIPADDR,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPAddr),\
},\
{\
.name = DSTIPADDR,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPAddr),\
},\
{\
.name = SRCIPMASK,\
.datatype = DATATYPE_IPMASK,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPMask),\
},\
{\
.name = DSTIPMASK,\
.datatype = DATATYPE_IPMASK,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPMask),\
},\
{\
.name = SRCIPFROM,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPFrom),\
},\
{\
.name = SRCIPTO,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataSrcIPTo),\
},\
{\
.name = DSTIPFROM,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPFrom),\
},\
{\
.name = DSTIPTO,\
.datatype = DATATYPE_IPADDR,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDstIPTo),\
},\
{\
.name = DSCP,\
.datatype = DATATYPE_UINT8,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.ipHdr.dataDSCP),\
.validator = dscpValidator,\
}
#define COMMON_PORT_PROPS(STRUCT) \
{\
.name = SRCPORTSTART,\
.datatype = DATATYPE_UINT16,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortStart),\
},\
{\
.name = SRCPORTEND,\
.datatype = DATATYPE_UINT16,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataSrcPortEnd),\
},\
{\
.name = DSTPORTSTART,\
.datatype = DATATYPE_UINT16,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortStart),\
},\
{\
.name = DSTPORTEND,\
.datatype = DATATYPE_UINT16,\
.dataIdx = offsetof(virNWFilterRuleDef, p.STRUCT.portData.dataDstPortEnd),\
}
static const virXMLAttr2Struct tcpAttributes[] = {
COMMON_IP_PROPS(tcpHdrFilter),
COMMON_PORT_PROPS(tcpHdrFilter),
{
.name = "option",
.datatype = DATATYPE_UINT8,
.dataIdx = offsetof(virNWFilterRuleDef, p.tcpHdrFilter.dataTCPOption),
},
{
.name = NULL,
}
};
static const virXMLAttr2Struct udpAttributes[] = {
COMMON_IP_PROPS(udpHdrFilter),
COMMON_PORT_PROPS(udpHdrFilter),
{
.name = NULL,
}
};
static const virXMLAttr2Struct sctpAttributes[] = {
COMMON_IP_PROPS(sctpHdrFilter),
COMMON_PORT_PROPS(sctpHdrFilter),
{
.name = NULL,
}
};
static const virXMLAttr2Struct icmpAttributes[] = {
COMMON_IP_PROPS(icmpHdrFilter),
{
.name = "type",
.datatype = DATATYPE_UINT8,
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPType),
},
{
.name = "code",
.datatype = DATATYPE_UINT8,
.dataIdx = offsetof(virNWFilterRuleDef, p.icmpHdrFilter.dataICMPCode),
},
{
.name = NULL,
}
};
static const virXMLAttr2Struct allAttributes[] = {
COMMON_IP_PROPS(allHdrFilter),
{
.name = NULL,
}
};
static const virXMLAttr2Struct igmpAttributes[] = {
COMMON_IP_PROPS(igmpHdrFilter),
{
.name = NULL,
}
};
typedef struct _virAttributes virAttributes; typedef struct _virAttributes virAttributes;
struct _virAttributes { struct _virAttributes {
const char *id; const char *id;
@ -856,6 +1020,30 @@ static const virAttributes virAttr[] = {
.id = "ipv6", .id = "ipv6",
.att = ipv6Attributes, .att = ipv6Attributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_IPV6, .prtclType = VIR_NWFILTER_RULE_PROTOCOL_IPV6,
}, {
.id = "tcp",
.att = tcpAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_TCP,
}, {
.id = "udp",
.att = udpAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_UDP,
}, {
.id = "sctp",
.att = sctpAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_SCTP,
}, {
.id = "icmp",
.att = icmpAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_ICMP,
}, {
.id = "all", // = 'any'
.att = allAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_ALL,
}, {
.id = "igmp",
.att = igmpAttributes,
.prtclType = VIR_NWFILTER_RULE_PROTOCOL_IGMP,
}, { }, {
.id = NULL, .id = NULL,
} }
@ -1274,8 +1462,96 @@ virNWFilterRuleDefFixup(virNWFilterRuleDefPtr rule)
case VIR_NWFILTER_RULE_PROTOCOL_ARP: case VIR_NWFILTER_RULE_PROTOCOL_ARP:
case VIR_NWFILTER_RULE_PROTOCOL_NONE: case VIR_NWFILTER_RULE_PROTOCOL_NONE:
break; break;
}
case VIR_NWFILTER_RULE_PROTOCOL_TCP:
COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcIPMask,
rule->p.tcpHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPMask,
rule->p.tcpHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataSrcIPTo,
rule->p.tcpHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.ipHdr.dataDstIPTo,
rule->p.tcpHdrFilter.ipHdr.dataDstIPFrom);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataSrcPortEnd,
rule->p.tcpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortStart,
rule->p.tcpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.tcpHdrFilter.portData.dataDstPortEnd,
rule->p.tcpHdrFilter.portData.dataSrcPortStart);
break;
case VIR_NWFILTER_RULE_PROTOCOL_UDP:
COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcIPMask,
rule->p.udpHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPMask,
rule->p.udpHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataSrcIPTo,
rule->p.udpHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.udpHdrFilter.ipHdr.dataDstIPTo,
rule->p.udpHdrFilter.ipHdr.dataDstIPFrom);
COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataSrcPortEnd,
rule->p.udpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortStart,
rule->p.udpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.udpHdrFilter.portData.dataDstPortEnd,
rule->p.udpHdrFilter.portData.dataSrcPortStart);
break;
case VIR_NWFILTER_RULE_PROTOCOL_SCTP:
COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPMask,
rule->p.sctpHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPMask,
rule->p.sctpHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataSrcIPTo,
rule->p.sctpHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.ipHdr.dataDstIPTo,
rule->p.sctpHdrFilter.ipHdr.dataDstIPFrom);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataSrcPortEnd,
rule->p.sctpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortStart,
rule->p.sctpHdrFilter.portData.dataSrcPortStart);
COPY_NEG_SIGN(rule->p.sctpHdrFilter.portData.dataDstPortEnd,
rule->p.sctpHdrFilter.portData.dataSrcPortStart);
break;
case VIR_NWFILTER_RULE_PROTOCOL_ICMP:
COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcIPMask,
rule->p.icmpHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPMask,
rule->p.icmpHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataSrcIPTo,
rule->p.icmpHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.icmpHdrFilter.ipHdr.dataDstIPTo,
rule->p.icmpHdrFilter.ipHdr.dataDstIPFrom);
COPY_NEG_SIGN(rule->p.icmpHdrFilter.dataICMPCode,
rule->p.icmpHdrFilter.dataICMPType);
break;
case VIR_NWFILTER_RULE_PROTOCOL_ALL:
COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPMask,
rule->p.allHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPMask,
rule->p.allHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataSrcIPTo,
rule->p.allHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.allHdrFilter.ipHdr.dataDstIPTo,
rule->p.allHdrFilter.ipHdr.dataDstIPFrom);
break;
case VIR_NWFILTER_RULE_PROTOCOL_IGMP:
COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPMask,
rule->p.igmpHdrFilter.ipHdr.dataSrcIPAddr);
COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPMask,
rule->p.igmpHdrFilter.ipHdr.dataDstIPAddr);
COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataSrcIPTo,
rule->p.igmpHdrFilter.ipHdr.dataSrcIPFrom);
COPY_NEG_SIGN(rule->p.igmpHdrFilter.ipHdr.dataDstIPTo,
rule->p.igmpHdrFilter.ipHdr.dataDstIPFrom);
break;
case VIR_NWFILTER_RULE_PROTOCOL_LAST:
break;
}
#undef COPY_NEG_SIGN #undef COPY_NEG_SIGN
} }

View File

@ -150,6 +150,10 @@ struct _ipHdrDataDef {
nwItemDesc dataDstIPAddr; nwItemDesc dataDstIPAddr;
nwItemDesc dataDstIPMask; nwItemDesc dataDstIPMask;
nwItemDesc dataProtocolID; nwItemDesc dataProtocolID;
nwItemDesc dataSrcIPFrom;
nwItemDesc dataSrcIPTo;
nwItemDesc dataDstIPFrom;
nwItemDesc dataDstIPTo;
nwItemDesc dataDSCP; nwItemDesc dataDSCP;
}; };
@ -182,6 +186,61 @@ struct _ipv6HdrFilterDef {
}; };
typedef struct _icmpHdrFilterDef icmpHdrFilterDef;
typedef icmpHdrFilterDef *icmpHdrFilterDefPtr;
struct _icmpHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
nwItemDesc dataICMPType;
nwItemDesc dataICMPCode;
nwItemDesc dataStateFlags;
};
typedef struct _allHdrFilterDef allHdrFilterDef;
typedef allHdrFilterDef *allHdrFilterDefPtr;
struct _allHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
};
typedef struct _igmpHdrFilterDef igmpHdrFilterDef;
typedef igmpHdrFilterDef *igmpHdrFilterDefPtr;
struct _igmpHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
};
typedef struct _tcpHdrFilterDef tcpHdrFilterDef;
typedef tcpHdrFilterDef *tcpHdrFilterDefPtr;
struct _tcpHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
portDataDef portData;
nwItemDesc dataTCPOption;
};
typedef struct _udpHdrFilterDef udpHdrFilterDef;
typedef udpHdrFilterDef *udpHdrFilterDefPtr;
struct _udpHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
portDataDef portData;
};
typedef struct _sctpHdrFilterDef sctpHdrFilterDef;
typedef sctpHdrFilterDef *sctpHdrFilterDefPtr;
struct _sctpHdrFilterDef {
nwItemDesc dataSrcMACAddr;
ipHdrDataDef ipHdr;
portDataDef portData;
};
enum virNWFilterRuleActionType { enum virNWFilterRuleActionType {
VIR_NWFILTER_RULE_ACTION_DROP = 0, VIR_NWFILTER_RULE_ACTION_DROP = 0,
VIR_NWFILTER_RULE_ACTION_ACCEPT, VIR_NWFILTER_RULE_ACTION_ACCEPT,
@ -210,6 +269,14 @@ enum virNWFilterRuleProtocolType {
VIR_NWFILTER_RULE_PROTOCOL_ARP, VIR_NWFILTER_RULE_PROTOCOL_ARP,
VIR_NWFILTER_RULE_PROTOCOL_IP, VIR_NWFILTER_RULE_PROTOCOL_IP,
VIR_NWFILTER_RULE_PROTOCOL_IPV6, VIR_NWFILTER_RULE_PROTOCOL_IPV6,
VIR_NWFILTER_RULE_PROTOCOL_TCP,
VIR_NWFILTER_RULE_PROTOCOL_ICMP,
VIR_NWFILTER_RULE_PROTOCOL_IGMP,
VIR_NWFILTER_RULE_PROTOCOL_UDP,
VIR_NWFILTER_RULE_PROTOCOL_SCTP,
VIR_NWFILTER_RULE_PROTOCOL_ALL,
VIR_NWFILTER_RULE_PROTOCOL_LAST
}; };
enum virNWFilterEbtablesTableType { enum virNWFilterEbtablesTableType {
@ -236,6 +303,12 @@ struct _virNWFilterRuleDef {
arpHdrFilterDef arpHdrFilter; arpHdrFilterDef arpHdrFilter;
ipHdrFilterDef ipHdrFilter; ipHdrFilterDef ipHdrFilter;
ipv6HdrFilterDef ipv6HdrFilter; ipv6HdrFilterDef ipv6HdrFilter;
tcpHdrFilterDef tcpHdrFilter;
icmpHdrFilterDef icmpHdrFilter;
udpHdrFilterDef udpHdrFilter;
allHdrFilterDef allHdrFilter;
igmpHdrFilterDef igmpHdrFilter;
sctpHdrFilterDef sctpHdrFilter;
} p; } p;
int nvars; int nvars;

View File

@ -465,6 +465,7 @@ virNWFilterPoolObjListFree;
virNWFilterDefFormat; virNWFilterDefFormat;
virNWFilterChainSuffixTypeToString; virNWFilterChainSuffixTypeToString;
virNWFilterRuleActionTypeToString; virNWFilterRuleActionTypeToString;
virNWFilterRuleProtocolTypeToString;
virNWFilterJumpTargetTypeToString; virNWFilterJumpTargetTypeToString;
virNWFilterRegisterCallbackDriver; virNWFilterRegisterCallbackDriver;
virNWFilterTestUnassignDef; virNWFilterTestUnassignDef;

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,12 @@
#define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */ #define MAX_CHAINNAME_LENGTH 32 /* see linux/netfilter_bridge/ebtables.h */
enum RuleType {
RT_EBTABLES,
RT_IPTABLES,
/* RT_IP6TABLES, for future use */
};
typedef struct _ebiptablesRuleInst ebiptablesRuleInst; typedef struct _ebiptablesRuleInst ebiptablesRuleInst;
typedef ebiptablesRuleInst *ebiptablesRuleInstPtr; typedef ebiptablesRuleInst *ebiptablesRuleInstPtr;
struct _ebiptablesRuleInst { struct _ebiptablesRuleInst {
@ -32,6 +38,7 @@ struct _ebiptablesRuleInst {
enum virNWFilterChainSuffixType neededProtocolChain; enum virNWFilterChainSuffixType neededProtocolChain;
char chainprefix; // I for incoming, O for outgoing char chainprefix; // I for incoming, O for outgoing
unsigned int priority; unsigned int priority;
enum RuleType ruleType;
}; };
extern virNWFilterTechDriver ebiptables_driver; extern virNWFilterTechDriver ebiptables_driver;