ipv6: Add support for sending packets through a router
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 commit is contained in:
parent
978d2392e9
commit
39acf5a553
|
@ -13,6 +13,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -416,6 +417,21 @@ static uint8_t *ip6_to_multicast_mac(ip6_addr_t * ip, uint8_t *mc_mac)
|
||||||
return mc_mac;
|
return mc_mac;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether an IPv6 address is on the same network as we are
|
||||||
|
*/
|
||||||
|
static bool is_ip6addr_in_my_net(ip6_addr_t *ip)
|
||||||
|
{
|
||||||
|
struct ip6addr_list_entry *n = NULL;
|
||||||
|
|
||||||
|
for (n = first_ip6; n != NULL; n = n->next) {
|
||||||
|
if (n->addr.part.prefix == ip->part.prefix)
|
||||||
|
return true; /* IPv6 address is in our neighborhood */
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; /* not in our neighborhood */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NET: calculate checksum over IPv6 header and upper-layer protocol
|
* NET: calculate checksum over IPv6 header and upper-layer protocol
|
||||||
* (e.g. UDP or ICMPv6)
|
* (e.g. UDP or ICMPv6)
|
||||||
|
@ -517,6 +533,10 @@ int send_ipv6(int fd, void* buffer, int len)
|
||||||
if (n) {
|
if (n) {
|
||||||
if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
|
if (memcmp(n->mac, null_mac, ETH_ALEN) != 0)
|
||||||
memcpy (mac_addr, &(n->mac), ETH_ALEN); /* found it */
|
memcpy (mac_addr, &(n->mac), ETH_ALEN); /* found it */
|
||||||
|
} else if (!is_ip6addr_in_my_net(&ip_dst)) {
|
||||||
|
struct router *gw;
|
||||||
|
gw = ipv6_get_default_router(&ip6h->src);
|
||||||
|
mac_addr = gw ? gw->mac : null_mac;
|
||||||
} else {
|
} else {
|
||||||
mac_addr = null_mac;
|
mac_addr = null_mac;
|
||||||
n = malloc(sizeof(struct neighbor));
|
n = malloc(sizeof(struct neighbor));
|
||||||
|
@ -547,6 +567,9 @@ int send_ipv6(int fd, void* buffer, int len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mac_addr == null_mac)
|
||||||
|
return -1;
|
||||||
|
|
||||||
fill_ethhdr (n->eth_frame, htons(ETHERTYPE_IPv6), get_mac_address(),
|
fill_ethhdr (n->eth_frame, htons(ETHERTYPE_IPv6), get_mac_address(),
|
||||||
mac_addr);
|
mac_addr);
|
||||||
memcpy (&(n->eth_frame[sizeof(struct ethhdr)]), buffer, len);
|
memcpy (&(n->eth_frame[sizeof(struct ethhdr)]), buffer, len);
|
||||||
|
|
|
@ -84,6 +84,23 @@ find_router( ip6_addr_t *ip )
|
||||||
return NULL; /* router is unknown */
|
return NULL; /* router is unknown */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a router for a given host address
|
||||||
|
* @param ip - IPv6 address with the prefered prefix
|
||||||
|
* @return pointer to router, or NULL if none is available
|
||||||
|
*/
|
||||||
|
struct router *ipv6_get_default_router(ip6_addr_t *ip)
|
||||||
|
{
|
||||||
|
struct router *n = NULL;
|
||||||
|
|
||||||
|
for (n = first_router; n != NULL; n = n->next) {
|
||||||
|
if (n->ip.part.prefix == ip->part.prefix)
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return first_router;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NET: add new neighbor to list
|
* NET: add new neighbor to list
|
||||||
* @param struct neighbor nghb - new neighbor
|
* @param struct neighbor nghb - new neighbor
|
||||||
|
|
|
@ -67,5 +67,6 @@ struct neighbor * find_neighbor (ip6_addr_t *);
|
||||||
int8_t router_add(struct router*);
|
int8_t router_add(struct router*);
|
||||||
void * router_create(uint8_t *mac, ip6_addr_t *ip);
|
void * router_create(uint8_t *mac, ip6_addr_t *ip);
|
||||||
struct router * find_router(ip6_addr_t *);
|
struct router * find_router(ip6_addr_t *);
|
||||||
|
struct router *ipv6_get_default_router(ip6_addr_t *ip);
|
||||||
|
|
||||||
#endif //_NDP_H_
|
#endif //_NDP_H_
|
||||||
|
|
Loading…
Reference in New Issue