* IPv4 must always set the net_buffer::interface_address on incoming buffers; it

didn't do that for broadcasts - this is still not a full solution as it won't
  work for link layer broadcasts, but this should fix most DHCP problems.
* IPv4 multicast doesn't do that yet.
* Only send ICMP errors if it hasn't been a link layer broadcast.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38356 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2010-08-25 15:54:35 +00:00
parent cb99c9153b
commit 4c6e53f601
@@ -1579,7 +1579,8 @@ ipv4_receive_data(net_buffer* buffer)
return B_BAD_DATA; return B_BAD_DATA;
// lower layers notion of broadcast or multicast have no relevance to us // lower layers notion of broadcast or multicast have no relevance to us
// TODO: they actually have when deciding whether to send an ICMP error // other than deciding whether to send an ICMP error
bool wasMulticast = (buffer->flags & (MSG_BCAST | MSG_MCAST)) != 0;
buffer->flags &= ~(MSG_BCAST | MSG_MCAST); buffer->flags &= ~(MSG_BCAST | MSG_MCAST);
sockaddr_in destination; sockaddr_in destination;
@@ -1587,27 +1588,41 @@ ipv4_receive_data(net_buffer* buffer)
if (header.destination == INADDR_BROADCAST) { if (header.destination == INADDR_BROADCAST) {
buffer->flags |= MSG_BCAST; buffer->flags |= MSG_BCAST;
// Find first interface with a matching family
// TODO: support for ethernet broadcasts!
// TODO: we might need to send it to all interfaces if it's an ethernet
// broadcast as well!
sDatalinkModule->is_local_link_address(sDomain, true,
buffer->destination, &buffer->interface_address);
} else if (IN_MULTICAST(ntohl(header.destination))) { } else if (IN_MULTICAST(ntohl(header.destination))) {
buffer->flags |= MSG_MCAST; buffer->flags |= MSG_MCAST;
// TODO: must set buffer->interface_address!
} else { } else {
uint32 matchedAddressType = 0; uint32 matchedAddressType = 0;
// test if the packet is really for us // test if the packet is really for us
if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination, if (!sDatalinkModule->is_local_address(sDomain, (sockaddr*)&destination,
&buffer->interface_address, &matchedAddressType) &buffer->interface_address, &matchedAddressType)) {
&& !sDatalinkModule->is_local_link_address(sDomain, true, sDatalinkModule->is_local_link_address(sDomain, true,
buffer->destination, &buffer->interface_address)) { buffer->destination, &buffer->interface_address);
} else {
// copy over special address types (MSG_BCAST or MSG_MCAST):
buffer->flags |= matchedAddressType;
}
}
if (buffer->interface_address == NULL) {
TRACE(" ipv4_receive_data(): packet was not for us %x -> %x", TRACE(" ipv4_receive_data(): packet was not for us %x -> %x",
ntohl(header.source), ntohl(header.destination)); ntohl(header.source), ntohl(header.destination));
if (!wasMulticast) {
// Send ICMP error: Host unreachable // Send ICMP error: Host unreachable
sDomain->module->error_reply(NULL, buffer, B_NET_ERROR_UNREACH_HOST, sDomain->module->error_reply(NULL, buffer, B_NET_ERROR_UNREACH_HOST,
NULL); NULL);
return B_ERROR;
} }
// copy over special address types (MSG_BCAST or MSG_MCAST): return B_ERROR;
buffer->flags |= matchedAddressType;
} }
// set net_buffer's source/destination address // set net_buffer's source/destination address