This patch adds support for the RARP protocol. This may be needed due to qemu sending out a RARP packet (at least that's what it seems to want to do even though the protocol id is wrong) when migration finishes and we'd need a rule to let the packets pass. Unfortunately my installation of ebtables does not understand -p RARP and also seems to otherwise depend on strings in /etc/ethertype translated to protocol identifiers. Therefore I need to pass -p 0x8035 for RARP. To generally get rid of the dependency of that file I switch all so far supported protocols to use their protocol identifier in the -p parameter rather than the string. I am also extending the schema. Signed-off-by: Stefan Berger <stefanb@xxxxxxxxxx> --- docs/schemas/nwfilter.rng | 9 ++ src/conf/nwfilter_conf.c | 29 ++----- src/conf/nwfilter_conf.h | 22 +++++- src/nwfilter/nwfilter_ebiptables_driver.c | 109 ++++++++++++++++++------------ 4 files changed, 106 insertions(+), 63 deletions(-) Index: libvirt-acl/docs/schemas/nwfilter.rng =================================================================== --- libvirt-acl.orig/docs/schemas/nwfilter.rng +++ libvirt-acl/docs/schemas/nwfilter.rng @@ -39,6 +39,15 @@ </optional> <optional> <zeroOrMore> + <element name="rarp"> + <ref name="match-attribute"/> + <ref name="common-l2-attributes"/> + <ref name="arp-attributes"/> <!-- same as arp --> + </element> + </zeroOrMore> + </optional> + <optional> + <zeroOrMore> <element name="ip"> <ref name="match-attribute"/> <ref name="common-l2-attributes"/> Index: libvirt-acl/src/conf/nwfilter_conf.c =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.c +++ libvirt-acl/src/conf/nwfilter_conf.c @@ -46,22 +46,6 @@ #include "domain_conf.h" -/* XXX - * The config parser/structs should not be using platform specific - * constants. Win32 lacks these constants, breaking the parser, - * so temporarily define them until this can be re-written to use - * locally defined enums for all constants - */ -#ifndef ETHERTYPE_IP -# define ETHERTYPE_IP 0x0800 -#endif -#ifndef ETHERTYPE_ARP -# define ETHERTYPE_ARP 0x0806 -#endif -#ifndef ETHERTYPE_IPV6 -# define ETHERTYPE_IPV6 0x86dd -#endif - #define VIR_FROM_THIS VIR_FROM_NWFILTER @@ -90,6 +74,7 @@ VIR_ENUM_IMPL(virNWFilterEbtablesTable, VIR_ENUM_IMPL(virNWFilterChainSuffix, VIR_NWFILTER_CHAINSUFFIX_LAST, "root", "arp", + "rarp", "ipv4", "ipv6"); @@ -97,6 +82,7 @@ VIR_ENUM_IMPL(virNWFilterRuleProtocol, V "none", "mac", "arp", + "rarp", "ip", "ipv6", "tcp", @@ -412,11 +398,10 @@ struct _virXMLAttr2Struct static const struct int_map macProtoMap[] = { - INTMAP_ENTRY(ETHERTYPE_ARP , "arp"), - INTMAP_ENTRY(ETHERTYPE_IP , "ipv4"), -#ifdef ETHERTYPE_IPV6 - INTMAP_ENTRY(ETHERTYPE_IPV6, "ipv6"), -#endif + INTMAP_ENTRY(ETHERTYPE_ARP , "arp"), + INTMAP_ENTRY(ETHERTYPE_REVARP, "rarp"), + INTMAP_ENTRY(ETHERTYPE_IP , "ipv4"), + INTMAP_ENTRY(ETHERTYPE_IPV6 , "ipv6"), INTMAP_ENTRY_LAST }; @@ -1084,6 +1069,7 @@ struct _virAttributes { static const virAttributes virAttr[] = { PROTOCOL_ENTRY("arp" , arpAttributes , VIR_NWFILTER_RULE_PROTOCOL_ARP), + PROTOCOL_ENTRY("rarp" , arpAttributes , VIR_NWFILTER_RULE_PROTOCOL_RARP), PROTOCOL_ENTRY("mac" , macAttributes , VIR_NWFILTER_RULE_PROTOCOL_MAC), PROTOCOL_ENTRY("ip" , ipAttributes , VIR_NWFILTER_RULE_PROTOCOL_IP), PROTOCOL_ENTRY("ipv6" , ipv6Attributes , VIR_NWFILTER_RULE_PROTOCOL_IPV6), @@ -1434,6 +1420,7 @@ virNWFilterRuleDefFixup(virNWFilterRuleD break; case VIR_NWFILTER_RULE_PROTOCOL_ARP: + case VIR_NWFILTER_RULE_PROTOCOL_RARP: case VIR_NWFILTER_RULE_PROTOCOL_NONE: break; Index: libvirt-acl/src/conf/nwfilter_conf.h =================================================================== --- libvirt-acl.orig/src/conf/nwfilter_conf.h +++ libvirt-acl/src/conf/nwfilter_conf.h @@ -35,6 +35,24 @@ # include "xml.h" # include "network.h" +/* XXX + * The config parser/structs should not be using platform specific + * constants. Win32 lacks these constants, breaking the parser, + * so temporarily define them until this can be re-written to use + * locally defined enums for all constants + */ +# ifndef ETHERTYPE_IP +# define ETHERTYPE_IP 0x0800 +# endif +# ifndef ETHERTYPE_ARP +# define ETHERTYPE_ARP 0x0806 +# endif +# ifndef ETHERTYPE_REVARP +# define ETHERTYPE_REVARP 0x8035 +# endif +# ifndef ETHERTYPE_IPV6 +# define ETHERTYPE_IPV6 0x86dd +# endif /** * Chain suffix size is: @@ -290,6 +308,7 @@ enum virNWFilterRuleProtocolType { VIR_NWFILTER_RULE_PROTOCOL_NONE = 0, VIR_NWFILTER_RULE_PROTOCOL_MAC, VIR_NWFILTER_RULE_PROTOCOL_ARP, + VIR_NWFILTER_RULE_PROTOCOL_RARP, VIR_NWFILTER_RULE_PROTOCOL_IP, VIR_NWFILTER_RULE_PROTOCOL_IPV6, VIR_NWFILTER_RULE_PROTOCOL_TCP, @@ -334,7 +353,7 @@ struct _virNWFilterRuleDef { enum virNWFilterRuleProtocolType prtclType; union { ethHdrFilterDef ethHdrFilter; - arpHdrFilterDef arpHdrFilter; + arpHdrFilterDef arpHdrFilter; /* also used for rarp */ ipHdrFilterDef ipHdrFilter; ipv6HdrFilterDef ipv6HdrFilter; tcpHdrFilterDef tcpHdrFilter; @@ -371,6 +390,7 @@ struct _virNWFilterEntry { enum virNWFilterChainSuffixType { VIR_NWFILTER_CHAINSUFFIX_ROOT = 0, VIR_NWFILTER_CHAINSUFFIX_ARP, + VIR_NWFILTER_CHAINSUFFIX_RARP, VIR_NWFILTER_CHAINSUFFIX_IPv4, VIR_NWFILTER_CHAINSUFFIX_IPv6, Index: libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c =================================================================== --- libvirt-acl.orig/src/nwfilter/nwfilter_ebiptables_driver.c +++ libvirt-acl/src/nwfilter/nwfilter_ebiptables_driver.c @@ -32,6 +32,7 @@ #include "logging.h" #include "virterror_internal.h" #include "domain_conf.h" +#include "nwfilter_conf.h" #include "nwfilter_gentech_driver.h" #include "nwfilter_ebiptables_driver.h" @@ -103,11 +104,28 @@ static int ebiptablesDriverInit(void); static void ebiptablesDriverShutdown(void); -static const char *supported_protocols[] = { - "ipv4", - "ipv6", - "arp", - NULL, +struct ushort_map { + unsigned short attr; + const char *val; +}; + + +enum l3_proto_idx { + L3_PROTO_IPV4_IDX = 0, + L3_PROTO_IPV6_IDX, + L3_PROTO_ARP_IDX, + L3_PROTO_RARP_IDX, + L3_PROTO_LAST_IDX +}; + +#define USHORTMAP_ENTRY_IDX(IDX, ATT, VAL) [IDX] = { .attr = ATT, .val = VAL } + +static const struct ushort_map l3_protocols[] = { + USHORTMAP_ENTRY_IDX(L3_PROTO_IPV4_IDX, ETHERTYPE_IP , "ipv4"), + USHORTMAP_ENTRY_IDX(L3_PROTO_IPV6_IDX, ETHERTYPE_IPV6 , "ipv6"), + USHORTMAP_ENTRY_IDX(L3_PROTO_ARP_IDX , ETHERTYPE_ARP , "arp"), + USHORTMAP_ENTRY_IDX(L3_PROTO_RARP_IDX, ETHERTYPE_REVARP, "rarp"), + USHORTMAP_ENTRY_IDX(L3_PROTO_LAST_IDX, 0 , NULL), }; @@ -1609,6 +1627,7 @@ ebtablesCreateRuleInstance(char chainPre break; case VIR_NWFILTER_RULE_PROTOCOL_ARP: + case VIR_NWFILTER_RULE_PROTOCOL_RARP: virBufferVSprintf(&buf, CMD_DEF_PRE "%s -t %s -%%c %s %%s", @@ -1620,7 +1639,10 @@ ebtablesCreateRuleInstance(char chainPre reverse)) goto err_exit; - virBufferAddLit(&buf, " -p arp"); + virBufferVSprintf(&buf, " -p 0x%x", + (rule->prtclType == VIR_NWFILTER_RULE_PROTOCOL_ARP) + ? l3_protocols[L3_PROTO_ARP_IDX].attr + : l3_protocols[L3_PROTO_RARP_IDX].attr); if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataHWType)) { if (printDataType(vars, @@ -2034,6 +2056,7 @@ ebiptablesCreateRuleInstance(virConnectP case VIR_NWFILTER_RULE_PROTOCOL_IP: case VIR_NWFILTER_RULE_PROTOCOL_MAC: case VIR_NWFILTER_RULE_PROTOCOL_ARP: + case VIR_NWFILTER_RULE_PROTOCOL_RARP: case VIR_NWFILTER_RULE_PROTOCOL_NONE: case VIR_NWFILTER_RULE_PROTOCOL_IPV6: @@ -2425,7 +2448,7 @@ static int ebtablesCreateTmpSubChain(virBufferPtr buf, int incoming, const char *ifname, - const char *protocol, + enum l3_proto_idx protoidx, int stopOnError) { char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; @@ -2433,13 +2456,13 @@ ebtablesCreateTmpSubChain(virBufferPtr b : CHAINPREFIX_HOST_OUT_TEMP; PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname); - PRINT_CHAIN(chain, chainPrefix, ifname, protocol); + PRINT_CHAIN(chain, chainPrefix, ifname, l3_protocols[protoidx].val); virBufferVSprintf(buf, CMD_DEF("%s -t %s -N %s") CMD_SEPARATOR CMD_EXEC "%s" - CMD_DEF("%s -t %s -A %s -p %s -j %s") CMD_SEPARATOR + CMD_DEF("%s -t %s -A %s -p 0x%x -j %s") CMD_SEPARATOR CMD_EXEC "%s", @@ -2448,7 +2471,7 @@ ebtablesCreateTmpSubChain(virBufferPtr b CMD_STOPONERR(stopOnError), ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, - rootchain, protocol, chain, + rootchain, l3_protocols[protoidx].attr, chain, CMD_STOPONERR(stopOnError)); @@ -2460,11 +2483,12 @@ static int _ebtablesRemoveSubChain(virBufferPtr buf, int incoming, const char *ifname, - const char *protocol, + enum l3_proto_idx protoidx, int isTempChain) { char rootchain[MAX_CHAINNAME_LENGTH], chain[MAX_CHAINNAME_LENGTH]; char chainPrefix; + if (isTempChain) { chainPrefix =(incoming) ? CHAINPREFIX_HOST_IN_TEMP : CHAINPREFIX_HOST_OUT_TEMP; @@ -2474,14 +2498,14 @@ _ebtablesRemoveSubChain(virBufferPtr buf } PRINT_ROOT_CHAIN(rootchain, chainPrefix, ifname); - PRINT_CHAIN(chain, chainPrefix, ifname, protocol); + PRINT_CHAIN(chain, chainPrefix, ifname, l3_protocols[protoidx].val); virBufferVSprintf(buf, - "%s -t %s -D %s -p %s -j %s" CMD_SEPARATOR + "%s -t %s -D %s -p 0x%x -j %s" CMD_SEPARATOR "%s -t %s -F %s" CMD_SEPARATOR "%s -t %s -X %s" CMD_SEPARATOR, ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, - rootchain, protocol, chain, + rootchain, l3_protocols[protoidx].attr, chain, ebtables_cmd_path, EBTABLES_DEFAULT_TABLE, chain, @@ -2495,10 +2519,10 @@ static int ebtablesRemoveSubChain(virBufferPtr buf, int incoming, const char *ifname, - const char *protocol) + enum l3_proto_idx protoidx) { return _ebtablesRemoveSubChain(buf, - incoming, ifname, protocol, 0); + incoming, ifname, protoidx, 0); } @@ -2506,10 +2530,11 @@ static int ebtablesRemoveSubChains(virBufferPtr buf, const char *ifname) { - int i; - for (i = 0; supported_protocols[i]; i++) { - ebtablesRemoveSubChain(buf, 1, ifname, supported_protocols[i]); - ebtablesRemoveSubChain(buf, 0, ifname, supported_protocols[i]); + enum l3_proto_idx i; + + for (i = 0; i < L3_PROTO_LAST_IDX; i++) { + ebtablesRemoveSubChain(buf, 1, ifname, i); + ebtablesRemoveSubChain(buf, 0, ifname, i); } return 0; @@ -2520,10 +2545,10 @@ static int ebtablesRemoveTmpSubChain(virBufferPtr buf, int incoming, const char *ifname, - const char *protocol) + enum l3_proto_idx protoidx) { return _ebtablesRemoveSubChain(buf, - incoming, ifname, protocol, 1); + incoming, ifname, protoidx, 1); } @@ -2531,12 +2556,11 @@ static int ebtablesRemoveTmpSubChains(virBufferPtr buf, const char *ifname) { - int i; - for (i = 0; supported_protocols[i]; i++) { - ebtablesRemoveTmpSubChain(buf, 1, ifname, - supported_protocols[i]); - ebtablesRemoveTmpSubChain(buf, 0, ifname, - supported_protocols[i]); + enum l3_proto_idx i; + + for (i = 0; i < L3_PROTO_LAST_IDX; i++) { + ebtablesRemoveTmpSubChain(buf, 1, ifname, i); + ebtablesRemoveTmpSubChain(buf, 0, ifname, i); } return 0; @@ -2574,12 +2598,11 @@ static int ebtablesRenameTmpSubChains(virBufferPtr buf, const char *ifname) { - int i; - for (i = 0; supported_protocols[i]; i++) { - ebtablesRenameTmpSubChain (buf, 1, ifname, - supported_protocols[i]); - ebtablesRenameTmpSubChain (buf, 0, ifname, - supported_protocols[i]); + enum l3_proto_idx i; + + for (i = 0; i < L3_PROTO_LAST_IDX; i++) { + ebtablesRenameTmpSubChain (buf, 1, ifname, l3_protocols[i].val); + ebtablesRenameTmpSubChain (buf, 0, ifname, l3_protocols[i].val); } return 0; @@ -2909,20 +2932,24 @@ ebiptablesApplyNewRules(virConnectPtr co ebtablesCreateTmpRootChain(&buf, 0, ifname, 1); if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4)) - ebtablesCreateTmpSubChain(&buf, 1, ifname, "ipv4", 1); + ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_IPV4_IDX, 1); if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv4)) - ebtablesCreateTmpSubChain(&buf, 0, ifname, "ipv4", 1); + ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_IPV4_IDX, 1); if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv6)) - ebtablesCreateTmpSubChain(&buf, 1, ifname, "ipv6", 1); + ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_IPV6_IDX, 1); if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_IPv6)) - ebtablesCreateTmpSubChain(&buf, 0, ifname, "ipv6", 1); + ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_IPV6_IDX, 1); - // keep arp as last + // keep arp,rarp as last if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP)) - ebtablesCreateTmpSubChain(&buf, 1, ifname, "arp", 1); + ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_ARP_IDX, 1); if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_ARP)) - ebtablesCreateTmpSubChain(&buf, 0, ifname, "arp", 1); + ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_ARP_IDX, 1); + if (chains_in & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP)) + ebtablesCreateTmpSubChain(&buf, 1, ifname, L3_PROTO_RARP_IDX, 1); + if (chains_out & (1 << VIR_NWFILTER_CHAINSUFFIX_RARP)) + ebtablesCreateTmpSubChain(&buf, 0, ifname, L3_PROTO_RARP_IDX, 1); if (ebiptablesExecCLI(&buf, &cli_status) || cli_status != 0) goto tear_down_tmpebchains; -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list