grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4));
rname = grub_xasprintf ("%s:default", name);
if (rname)
- grub_net_add_route_gw (rname, target, gw);
+ grub_net_add_route_gw (rname, target, gw, NULL);
grub_free (rname);
}
break;
grub_net_network_level_address_t client_addr, gateway_addr, subnet_mask;
grub_net_link_level_address_t hw_addr;
grub_net_interface_flags_t flags = 0;
- struct grub_net_network_level_interface *inter;
+ struct grub_net_network_level_interface *inter = NULL;
hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
target.ipv4.masksize = 0;
rname = grub_xasprintf ("%s:default", ((*card)->name));
if (rname)
- grub_net_add_route_gw (rname, target, gateway_addr);
+ grub_net_add_route_gw (rname, target, gateway_addr, inter);
else
return grub_errno;
}
grub_uint8_t ttl)
{
struct icmp_header *icmph;
+ struct grub_net_network_level_interface *orig_inf = inf;
grub_err_t err;
grub_uint16_t checksum;
{
grub_uint8_t *ptr;
struct option_header *ohdr;
+ struct router_adv *radv;
+ struct grub_net_network_level_interface *route_inf = NULL;
+ int default_route = 0;
if (icmph->code)
break;
+ radv = (struct router_adv *)nb->data;
err = grub_netbuff_pull (nb, sizeof (struct router_adv));
if (err)
{
grub_netbuff_free (nb);
return err;
}
+ if (grub_be_to_cpu16 (radv->router_lifetime) > 0)
+ {
+ struct grub_net_route *route;
+
+ FOR_NET_ROUTES (route)
+ {
+ if (!grub_memcmp (&route->gw, source, sizeof (route->gw)))
+ break;
+ }
+ if (route == NULL)
+ default_route = 1;
+ }
+
for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail;
ptr += ohdr->len * 8)
{
/* Update lease time if needed here once we have
lease times. */
if (inf)
- continue;
+ {
+ if (!route_inf)
+ route_inf = inf;
+ continue;
+ }
grub_dprintf ("net", "creating slaac\n");
inf = grub_net_add_addr (name,
card, &addr,
&slaac->address, 0);
+ if (!route_inf)
+ route_inf = inf;
grub_net_add_route (name, netaddr, inf);
grub_free (name);
}
}
}
}
+ if (default_route)
+ {
+ char *name;
+ grub_net_network_level_netaddress_t netaddr;
+ name = grub_xasprintf ("%s:ra:default6", card->name);
+ if (!name)
+ {
+ grub_errno = GRUB_ERR_NONE;
+ goto next;
+ }
+ /* Default routes take alll of the traffic, so make the mask huge */
+ netaddr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
+ netaddr.ipv6.masksize = 0;
+ netaddr.ipv6.base[0] = 0;
+ netaddr.ipv6.base[1] = 0;
+
+ /* May not have gotten slaac info, find a global address on this
+ card. */
+ if (route_inf == NULL)
+ {
+ FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
+ {
+ if (inf->card == card && inf != orig_inf
+ && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
+ && grub_net_hwaddr_cmp(&inf->hwaddress,
+ &orig_inf->hwaddress) == 0)
+ {
+ route_inf = inf;
+ break;
+ }
+ }
+ }
+ if (route_inf != NULL)
+ grub_net_add_route_gw (name, netaddr, *source, route_inf);
+ grub_free (name);
+ }
+next:
if (ptr != nb->tail)
break;
}
char *grub_net_default_server;
-struct grub_net_route
-{
- struct grub_net_route *next;
- struct grub_net_route **prev;
- grub_net_network_level_netaddress_t target;
- char *name;
- struct grub_net_network_level_protocol *prot;
- int is_gateway;
- union
- {
- struct grub_net_network_level_interface *interface;
- grub_net_network_level_address_t gw;
- };
-};
-
struct grub_net_route *grub_net_routes = NULL;
struct grub_net_network_level_interface *grub_net_network_level_interfaces = NULL;
struct grub_net_card *grub_net_cards = NULL;
return err;
}
-static inline void
-grub_net_route_register (struct grub_net_route *route)
-{
- grub_list_push (GRUB_AS_LIST_P (&grub_net_routes),
- GRUB_AS_LIST (route));
-}
-
-#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next)
static int
parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
{
grub_uint64_t mask[2];
+ if (net->ipv6.masksize == 0)
+ return 1;
if (net->ipv6.masksize <= 64)
{
mask[0] = 0xffffffffffffffffULL << (64 - net->ipv6.masksize);
return GRUB_ERR_NONE;
}
if (depth == 0)
- *gateway = bestroute->gw;
+ {
+ *gateway = bestroute->gw;
+ if (bestroute->interface != NULL)
+ {
+ *interf = bestroute->interface;
+ return GRUB_ERR_NONE;
+ }
+ }
curtarget = bestroute->gw;
}
grub_err_t
grub_net_add_route_gw (const char *name,
grub_net_network_level_netaddress_t target,
- grub_net_network_level_address_t gw)
+ grub_net_network_level_address_t gw,
+ struct grub_net_network_level_interface *inter)
{
struct grub_net_route *route;
route->target = target;
route->is_gateway = 1;
route->gw = gw;
+ route->interface = inter;
grub_net_route_register (route);
err = grub_net_resolve_address (args[3], &gw);
if (err)
return err;
- return grub_net_add_route_gw (args[0], target, gw);
+ return grub_net_add_route_gw (args[0], target, gw, NULL);
}
else
{
};
} grub_net_network_level_netaddress_t;
+struct grub_net_route
+{
+ struct grub_net_route *next;
+ struct grub_net_route **prev;
+ grub_net_network_level_netaddress_t target;
+ char *name;
+ struct grub_net_network_level_protocol *prot;
+ int is_gateway;
+ struct grub_net_network_level_interface *interface;
+ grub_net_network_level_address_t gw;
+};
+
#define FOR_PACKETS(cont,var) for (var = (cont).first; var; var = var->next)
static inline grub_err_t
#define FOR_NET_CARDS_SAFE(var, next) for (var = grub_net_cards, next = (var ? var->next : 0); var; var = next, next = (var ? var->next : 0))
+extern struct grub_net_route *grub_net_routes;
+
+static inline void
+grub_net_route_register (struct grub_net_route *route)
+{
+ grub_list_push (GRUB_AS_LIST_P (&grub_net_routes),
+ GRUB_AS_LIST (route));
+}
+
+#define FOR_NET_ROUTES(var) for (var = grub_net_routes; var; var = var->next)
struct grub_net_session *
grub_net_open_tcp (char *address, grub_uint16_t port);
grub_err_t
grub_net_add_route_gw (const char *name,
grub_net_network_level_netaddress_t target,
- grub_net_network_level_address_t gw);
+ grub_net_network_level_address_t gw,
+ struct grub_net_network_level_interface *inter);
#define GRUB_NET_BOOTP_MAC_ADDR_LEN 16