提交 c828a746 编写于 作者: S Stefan Berger 提交者: Daniel Veillard

nwfilter: accept broadcasted DHCP replies in DHCP snooping code

Some DHCP servers send their DHCP replies to the broadcast MAC address
rather than to the MAC address of the VM. The existing DHCP snooping
code assumes that the reply always goes to the MAC address of the VM
thus filtering the traffic of some DHCP servers' replies.

The below patch adapts the code to

1) filter DHCP replies by comparing the MAC address in the reply against
   the MAC address of the VM (held in the snoop request)

2) adapts the pcap filter for traffic towards the VM to accept DHCP replies
   sent to any MAC address; for further filtering we rely on 1)

3) creates initial rules that are active while waiting for DHCP replies;
   these rules now accept DHCP replies to the VM's MAC address or to the
   MAC broadcast address
上级 46b2cafb
...@@ -1010,6 +1010,17 @@ virNWFilterSnoopDHCPDecode(virNWFilterSnoopReqPtr req, ...@@ -1010,6 +1010,17 @@ virNWFilterSnoopDHCPDecode(virNWFilterSnoopReqPtr req,
if (len < 0) if (len < 0)
return -2; /* invalid packet length */ return -2; /* invalid packet length */
/*
* some DHCP servers send their responses as MAC broadcast replies
* filter messages from the server also by the destination MAC
* inside the DHCP response
*/
if (!fromVM) {
if (virMacAddrCmpRaw(&req->macaddr,
(unsigned char *)&pd->d_chaddr) != 0)
return -2;
}
if (virNWFilterSnoopDHCPGetOpt(pd, len, &mtype, &leasetime) < 0) if (virNWFilterSnoopDHCPGetOpt(pd, len, &mtype, &leasetime) < 0)
return -2; return -2;
...@@ -1069,7 +1080,6 @@ virNWFilterSnoopDHCPOpen(const char *ifname, virMacAddr *mac, ...@@ -1069,7 +1080,6 @@ virNWFilterSnoopDHCPOpen(const char *ifname, virMacAddr *mac,
char pcap_errbuf[PCAP_ERRBUF_SIZE]; char pcap_errbuf[PCAP_ERRBUF_SIZE];
char *ext_filter = NULL; char *ext_filter = NULL;
char macaddr[VIR_MAC_STRING_BUFLEN]; char macaddr[VIR_MAC_STRING_BUFLEN];
const char *ext;
virMacAddrFormat(mac, macaddr); virMacAddrFormat(mac, macaddr);
...@@ -1080,14 +1090,24 @@ virNWFilterSnoopDHCPOpen(const char *ifname, virMacAddr *mac, ...@@ -1080,14 +1090,24 @@ virNWFilterSnoopDHCPOpen(const char *ifname, virMacAddr *mac,
* extend the filter with the macaddr of the VM; filter the * extend the filter with the macaddr of the VM; filter the
* more unlikely parameters first, then go for the MAC * more unlikely parameters first, then go for the MAC
*/ */
ext = "and ether src"; if (virAsprintf(&ext_filter,
"%s and ether src %s", filter, macaddr) < 0) {
virReportOOMError();
return NULL;
}
} else { } else {
ext = "and ether dst"; /*
} * Some DHCP servers respond via MAC broadcast; we rely on later
* filtering of responses by comparing the MAC address inside the
if (virAsprintf(&ext_filter, "%s %s %s", filter, ext, macaddr) < 0) { * DHCP response against the one of the VM. Assuming that the
virReportOOMError(); * bridge learns the VM's MAC address quickly this should not
return NULL; * generate much more traffic than if we filtered by VM and
* braodcast MAC as well
*/
if (virAsprintf(&ext_filter, "%s", filter) < 0) {
virReportOOMError();
return NULL;
}
} }
handle = pcap_create(ifname, pcap_errbuf); handle = pcap_create(ifname, pcap_errbuf);
......
...@@ -3345,6 +3345,7 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, ...@@ -3345,6 +3345,7 @@ ebtablesApplyDHCPOnlyRules(const char *ifname,
while (true) { while (true) {
char *srcIPParam = NULL; char *srcIPParam = NULL;
int ctr;
if (idx < num_dhcpsrvrs) { if (idx < num_dhcpsrvrs) {
const char *dhcpserver; const char *dhcpserver;
...@@ -3357,20 +3358,26 @@ ebtablesApplyDHCPOnlyRules(const char *ifname, ...@@ -3357,20 +3358,26 @@ ebtablesApplyDHCPOnlyRules(const char *ifname,
} }
} }
virBufferAsprintf(&buf, /*
CMD_DEF("$EBT -t nat -A %s" * create two rules allowing response to MAC address of VM
" -d %s" * or to broadcast MAC address
" -p ipv4 --ip-protocol udp" */
" %s" for (ctr = 0; ctr < 2; ctr++) {
" --ip-sport 67 --ip-dport 68" virBufferAsprintf(&buf,
" -j ACCEPT") CMD_SEPARATOR CMD_DEF("$EBT -t nat -A %s"
CMD_EXEC " -d %s"
"%s", " -p ipv4 --ip-protocol udp"
" %s"
chain_out, " --ip-sport 67 --ip-dport 68"
macaddr_str, " -j ACCEPT") CMD_SEPARATOR
srcIPParam != NULL ? srcIPParam : "", CMD_EXEC
CMD_STOPONERR(1)); "%s",
chain_out,
(ctr == 0) ? macaddr_str : "ff:ff:ff:ff:ff:ff",
srcIPParam != NULL ? srcIPParam : "",
CMD_STOPONERR(1));
}
VIR_FREE(srcIPParam); VIR_FREE(srcIPParam);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册