The set_ipv6_address() function calls ip6_create_ll_address() to
get a link-local address. The latter function uses malloc to create
a buffer for composing that address, and returns the corresponding
poniter to the caller. However, set_ipv6_address() does not free
that buffer again, so the allocated memory is lost.
Since set_ipv6_address() already allocated space for the new IPv6
address anyway, let's fix this issue by passing the buffer from
set_ipv6_address() to ip6_create_ll_address() instead, so that
ip6_create_ll_address() does not have to allocate memory at all.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The IPv6 code uses malloc in a couple of places to allocate the memory
for a struct. But it does not properly initializes all members of the
struct after the allocation, so the uninitialized members might contain
random data. So we should better clear the whole memory for those
structs to make sure we do not run into some hard-to-reproduce random
problems later.
Reported-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The "struct neighbor *n" pointer in send_ipv6() can be NULL, e.g.
when we're sending to multicast addresses or to a server that sits
behind a router (since we do not have an entry in the neighbor cache
in this case).
However, the final code in send_ipv6() is always using n->eth_frame
to assemble the ethernet packet, and thus silently writes the data
into the low memory (which happens unnoticed because SLOF does not
use the MMU for memory protection).
This issue is now fixed by using a separate buffer for assembling
those ethernet packets instead. The block for using the router's
MAC address is also moved out of the block that is supposed to handle
the unicast transfers, so that we do not accidentially end up in the
neighbour solicitation code here (which also relies on n != NULL).
Reported-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Some parts of the IPv6 code are still indented with spaces. Let's
use tabs instead as mandated by the SLOF coding conventions.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The send_ipv6() function should return after doing NDP, since either
the queued packet got send out during handle_na() already, or it has
been stored to be sent out later (once the neighbor advertisment has
been received). If we don't return here, the code runs into the final
send_ether() here later, which then sends out the packet a second time.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The code in send_ipv6() currently basically looks like this:
uint8_t *mac_addr, mac[6];
mac_addr = mac;
...
n = find_neighbor (&ip_dst);
if (ip6_is_multicast (&ip_dst)) {
mac_addr = ip6_to_multicast_mac (&ip_dst, mac);
}
else {
// Check if the MAC address is already cached
if (n) {
if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
memcpy (mac_addr, &(n->mac), ETH_ALEN);
/* XXX */
}
...
}
...
fill_ethhdr (n->eth_frame, htons(ETHERTYPE_IPv6), get_mac_address(),
mac_addr);
That means mac_addr initially points to the uninitialized mac[6]
array on the stack. Now if there was already an entry in the neighbor
cache, but the MAC address has not been determined yet, that
uninitialized array could be used as final MAC address for fill_ethhdr()
(since there is no "else" path at the spot marked with XXX above),
resulting in random data in the MAC address field of the ethernet packet.
Let's fix this issue by letting mac_addr point to the null_mac by
default instead, so that it never points to invalid data. Also
rename mac[6] to mc_mac[6] to make it clear that this array is
only used for storing the multicast mac address.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The network boot over IPv6 currently fails if the TFTP server
is not in the same subnet as the SLOF client. In that case we
have to fill in the MAC address of a router into our packets
to get them to the right place.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
This replaces some local variable types and some function parameters from
signed to unsigned to fix gcc warnings.
Tested DHCP+TFTP on both IPv4 and IPv6.
The make command used to test:
make qemu WARNFLAGS=-Wextra
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Thomas Huth <thuth@redhat.com>
This restyles function prototypes:
- return types on the same line;
- opening brace is on the next line.
VIM configs used for this was:
set noexpandtab
set tabstop=8
set shiftwidth=4
set cino=:0,(0
This replaces [><]* with "*" as >< are also used to resolve merge
conflicts.
This removes trailing spaces.
This removes some redundant braces.
This should cause no behavioural change.
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Reviewed-by: Thomas Huth <thuth@redhat.com>
ip6_to_multicast_mac() uses a malloc to allocate a 6 bytes buffer
for the MAC address - which never gets freed again! That means
we're leaking memory for every multicast IPv6 packet that gets
send out. Fix it by simply using the "uint8_t mac[6]" array from
send_ipv6() instead.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The code that checks for NEIGHBOUR_SOLICITATION packets is bad
in two ways: First, it does not check that the packet is really
an ICMPv6 packet, so it could accidentially be triggered for UDP
or TCP packets, too. Second, the fill_ethhdr() is redundant (since
it is done at the end of the function again) and also wrong (it
uses the wrong buffer pointer to fill in the ethernet header).
All we really need here is to get the right MAC address via
ip6_to_multicast_mac() - and this is handled in the following
if-statement already (NEIGHBOUR_SOLICITATIONs are always sent
as multicast in the send_neighbour_solicitation() function), so
the bad code block can simply be removed to fix the two issues.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Using a memcpy to just compare one byte looks very cumbersome.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
The IPv6 code declares a bunch of global variables (without "extern"
keyword!) in the ipv6.h header file. This is bad style and does not
work when linking with "-fno-common" for example. So let's move
the variables to the files where they are used instead.
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
When the IPv6 code is told to create IPv6 addresses automatically
(by passing NULL as parameter to set_ipv6_address()), the netboot
code currently only uses link-local IPv6 addresses - which is bad
since they can not be routed, e.g. if the TFTP server is not on
the same link.
So set_ipv6_address(NULL) should set own_ip6 preferably to a non-local
unicast address if it has been generated successfully during ipv6_init().
Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
With module layer cleanup, and a fixed socket() call, start using the
fd across the network stack.
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
As per RFC 768 (UDP), if the computed checksum is zero, it is transmitted as all ones
(the equivalent in one's complement arithmetic).
Signed-off-by: Avik Sil <aviksil@linux.vnet.ibm.com>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
process_ra_options was going through infinite loop due to improper handling of option_length.
Also introduction of is_ra_received() makes booting time faster since it returns as soon as
router advertisement mesage is received.
Signed-off-by: Avik Sil <aviksil@linux.vnet.ibm.com>
Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
This patch adds support for booting from a IPv6 network. It gets the boot information
(tftp server, boot file name) from DHCPv6 server or can be specified manually using
obp-tftp arguments. To boot from a IPv6 network, type "boot net:ipv6" from the SLOF
prompt. To specify ipaddresses manually, type "boot net:ipv6,<si6addr>,<filename>,<ci6addr>"
from the SLOF prompt.
This patch is based on the IPv6 code written by the former SLOF team.
Signed-off-by: Avik Sil <aviksil@linux.vnet.ibm.com>