nwfilter: enable filtering of gratuitous ARP packets

This patch enables filtering of gratuitous ARP packets using the following XML:

<rule action='accept' direction='in' priority='425'>
<arp gratuitous='true'/>
</rule>
This commit is contained in:
Stefan Berger 2011-05-23 19:41:18 -04:00
parent 17266c5c68
commit fcb0e8c227
8 changed files with 68 additions and 2 deletions

View File

@ -321,6 +321,7 @@
<li>IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1</li> <li>IPV6_ADDR: IPv6 address in numbers format, i.e., FFFF::1</li>
<li>IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask (0-128)</li> <li>IPV6_MASK: IPv6 mask in numbers format (FFFF:FFFF:FC00::) or CIDR mask (0-128)</li>
<li>STRING: A string</li> <li>STRING: A string</li>
<li>BOOLEAN: 'true', 'yes', '1' or 'false', 'no', '0'</li>
</ul> </ul>
<p> <p>
<br/><br/> <br/><br/>
@ -476,6 +477,11 @@
<td>STRING</td> <td>STRING</td>
<td>text with max. 256 characters</td> <td>text with max. 256 characters</td>
</tr> </tr>
<tr>
<td>gratuitous <span class="since">(Since 0.9.2)</span></td>
<td>BOOLEAN</td>
<td>boolean indicating whether to check for gratuitous ARP packet</td>
</tr>
</table> </table>
<p> <p>
Valid strings for the <code>Opcode</code> field are: Valid strings for the <code>Opcode</code> field are:

View File

@ -581,6 +581,11 @@
<ref name="uint16range"/> <ref name="uint16range"/>
</attribute> </attribute>
</optional> </optional>
<optional>
<attribute name="gratuitous">
<ref name="boolean"/>
</attribute>
</optional>
</interleave> </interleave>
</define> </define>
@ -784,6 +789,17 @@
</choice> </choice>
</define> </define>
<define name="boolean">
<choice>
<value>yes</value>
<value>no</value>
<value>true</value>
<value>false</value>
<value>1</value>
<value>0</value>
</choice>
</define>
<define name="arpOpcodeType"> <define name="arpOpcodeType">
<choice> <choice>
<!-- variable --> <!-- variable -->

View File

@ -12,7 +12,11 @@
<rule action='drop' direction='out' priority='400' > <rule action='drop' direction='out' priority='400' >
<arp match='no' arpsrcipaddr='$IP' /> <arp match='no' arpsrcipaddr='$IP' />
</rule> </rule>
<!-- drop if ipaddr or macaddr odes not belong to guest --> <!-- allow gratuitous arp -->
<rule action='accept' direction='in' priority='425'>
<arp gratuitous='true'/>
</rule>
<!-- drop if ipaddr or macaddr does not belong to guest -->
<rule action='drop' direction='in' priority='450' > <rule action='drop' direction='in' priority='450' >
<arp match='no' arpdstmacaddr='$MAC'/> <arp match='no' arpdstmacaddr='$MAC'/>
<arp opcode='reply'/> <arp opcode='reply'/>

View File

@ -970,6 +970,10 @@ static const virXMLAttr2Struct arpAttributes[] = {
.name = ARPDSTIPADDR, .name = ARPDSTIPADDR,
.datatype = DATATYPE_IPADDR, .datatype = DATATYPE_IPADDR,
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr), .dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataARPDstIPAddr),
}, {
.name = "gratuitous",
.datatype = DATATYPE_BOOLEAN,
.dataIdx = offsetof(virNWFilterRuleDef, p.arpHdrFilter.dataGratuitousARP),
}, },
COMMENT_PROP(arpHdrFilter), COMMENT_PROP(arpHdrFilter),
{ {
@ -1611,6 +1615,18 @@ virNWFilterRuleDetailsParse(xmlNodePtr node,
found = 1; found = 1;
break; break;
case DATATYPE_BOOLEAN:
if (STREQ(prop, "true") ||
STREQ(prop, "1") ||
STREQ(prop, "yes"))
item->u.boolean = true;
else
item->u.boolean = false;
data.ui = item->u.boolean;
found = 1;
break;
case DATATYPE_LAST: case DATATYPE_LAST:
default: default:
break; break;
@ -2744,6 +2760,13 @@ virNWFilterRuleDefDetailsFormat(virBufferPtr buf,
virBufferEscapeString(buf, "%s", item->u.string); virBufferEscapeString(buf, "%s", item->u.string);
break; break;
case DATATYPE_BOOLEAN:
if (item->u.boolean == true)
virBufferAddLit(buf, "true");
else
virBufferAddLit(buf, "false");
break;
case DATATYPE_STRING: case DATATYPE_STRING:
default: default:
virBufferAsprintf(buf, virBufferAsprintf(buf,

View File

@ -97,8 +97,9 @@ enum attrDatatype {
DATATYPE_IPV6ADDR = (1 << 9), DATATYPE_IPV6ADDR = (1 << 9),
DATATYPE_IPV6MASK = (1 << 10), DATATYPE_IPV6MASK = (1 << 10),
DATATYPE_STRINGCOPY = (1 << 11), DATATYPE_STRINGCOPY = (1 << 11),
DATATYPE_BOOLEAN = (1 << 12),
DATATYPE_LAST = (1 << 12), DATATYPE_LAST = (1 << 13),
}; };
@ -118,6 +119,7 @@ struct _nwItemDesc {
union { union {
nwMACAddress macaddr; nwMACAddress macaddr;
virSocketAddr ipaddr; virSocketAddr ipaddr;
bool boolean;
uint8_t u8; uint8_t u8;
uint16_t u16; uint16_t u16;
char protocolID[10]; char protocolID[10];
@ -160,6 +162,7 @@ struct _arpHdrFilterDef {
nwItemDesc dataARPSrcIPAddr; nwItemDesc dataARPSrcIPAddr;
nwItemDesc dataARPDstMACAddr; nwItemDesc dataARPDstMACAddr;
nwItemDesc dataARPDstIPAddr; nwItemDesc dataARPDstIPAddr;
nwItemDesc dataGratuitousARP;
nwItemDesc dataComment; nwItemDesc dataComment;
}; };

View File

@ -2033,6 +2033,13 @@ ebtablesCreateRuleInstance(char chainPrefix,
ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr), ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataARPDstMACAddr),
macaddr); macaddr);
} }
if (HAS_ENTRY_ITEM(&rule->p.arpHdrFilter.dataGratuitousARP) &&
rule->p.arpHdrFilter.dataGratuitousARP.u.boolean) {
virBufferAsprintf(&buf,
" %s --arp-gratuitous",
ENTRY_GET_NEG_SIGN(&rule->p.arpHdrFilter.dataGratuitousARP));
}
break; break;
case VIR_NWFILTER_RULE_PROTOCOL_IP: case VIR_NWFILTER_RULE_PROTOCOL_IP:

View File

@ -30,4 +30,8 @@
<arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff' <arp srcmacaddr='1:2:3:4:5:6' srcmacmask='ff:ff:ff:ff:ff:ff'
opcode='65536' hwtype='65536' protocoltype='65536' /> opcode='65536' hwtype='65536' protocoltype='65536' />
</rule> </rule>
<rule action='accept' direction='in'>
<arp gratuitous='true'/>
</rule>
</filter> </filter>

View File

@ -15,4 +15,7 @@
<rule action='accept' direction='out' priority='500'> <rule action='accept' direction='out' priority='500'>
<arp srcmacaddr='01:02:03:04:05:06' srcmacmask='ff:ff:ff:ff:ff:ff'/> <arp srcmacaddr='01:02:03:04:05:06' srcmacmask='ff:ff:ff:ff:ff:ff'/>
</rule> </rule>
<rule action='accept' direction='in' priority='500'>
<arp gratuitous='true'/>
</rule>
</filter> </filter>