grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH V2] net: fix ipv6 routing


From: Vladimir 'φ-coder/phcoder' Serbinenko
Subject: Re: [PATCH V2] net: fix ipv6 routing
Date: Fri, 22 Jan 2016 14:01:45 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.5.0

Were Andrey's comments ever adressed? Other than his comments the patch
looks good.
On 20.09.2015 11:50, Andrei Borzenkov wrote:
> 28.08.2015 18:24, Josef Bacik пишет:
>> ipv6 routing in grub2 is broken, we cannot talk to anything outside
>> our local
>> network or anything that doesn't route in our global namespace.  This
>> patch
>> fixes this by doing a couple of things
>>
>> 1) Read the router information off of the router advertisement.  If we
>> have a
>> router lifetime we need to take the source address and create a route
>> from it.
>>
>> 2) Changes the routing stuff slightly to allow you to specify a
>> gateway _and_ an
>> interface.  Since the router advertisements come in on the link local
>> address we
>> need to associate it with the global address on the card.  So when we are
>> processing the router advertisement, either use the SLAAC interface we
>> create
>> and add the route to that interface, or loop through the global
>> addresses we
>> currently have on our interface and associate it with one of those
>> addresses.
>> We need to have a special case here for the default route so that it
>> gets used,
>> we do this by setting the masksize to 0 to mean it encompasses all
>> networks.
>> The routing code will automatically select the best route so if there
>> is a
>> closer match we will use that.
>>
> 
> I think this is OK; minor comments below. We probably want to augment
> net_route to allow both gateway and interface as well.
> 
>> With this patch I can now talk to ipv6 addresses outside of my local
>> network.
>> Thanks,
>>
>> Signed-off-by: Josef Bacik <address@hidden>
>> ---
>> V1->V2:
>> -reworked the route stuff to hold an interface for gateways as well.
>> -fixed the slaac stuff so the route information is separate from the
>> interface
>>   configuration
>>
>>   grub-core/net/bootp.c                  |  2 +-
>>   grub-core/net/drivers/ieee1275/ofnet.c |  4 +--
>>   grub-core/net/icmp6.c                  | 63
>> +++++++++++++++++++++++++++++++++-
>>   grub-core/net/net.c                    | 40 ++++++++-------------
>>   include/grub/net.h                     | 25 +++++++++++++-
>>   5 files changed, 103 insertions(+), 31 deletions(-)
>>
>> diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
>> index 37d1cfa..9fc47bd 100644
>> --- a/grub-core/net/bootp.c
>> +++ b/grub-core/net/bootp.c
>> @@ -83,7 +83,7 @@ parse_dhcp_vendor (const char *name, const void
>> *vend, int limit, int *mask)
>>             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;
>> diff --git a/grub-core/net/drivers/ieee1275/ofnet.c
>> b/grub-core/net/drivers/ieee1275/ofnet.c
>> index eea8e71..d238628 100644
>> --- a/grub-core/net/drivers/ieee1275/ofnet.c
>> +++ b/grub-core/net/drivers/ieee1275/ofnet.c
>> @@ -151,7 +151,7 @@ grub_ieee1275_parse_bootpath (const char *devpath,
>> char *bootpath,
>>     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;
>>
>> @@ -221,7 +221,7 @@ grub_ieee1275_parse_bootpath (const char *devpath,
>> char *bootpath,
>>         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;
>>       }
>> diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
>> index 7953e68..79a4a30 100644
>> --- a/grub-core/net/icmp6.c
>> +++ b/grub-core/net/icmp6.c
>> @@ -115,6 +115,7 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
>>                   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;
>>
>> @@ -345,8 +346,25 @@ grub_net_recv_icmp6_packet (struct grub_net_buff
>> *nb,
>>         {
>>       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 = (void *)nb->data;
>> +    if (grub_be_to_cpu16 (radv->router_lifetime) > 0)
> 
> This should come after grub_netbuff_pull error check to make sure we get
> ohis struct.
> 
> 
>> +      {
>> +        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;
>> +      }
>> +
>>       err = grub_netbuff_pull (nb, sizeof (struct router_adv));
>>       if (err)
>>         {
>> @@ -413,7 +431,11 @@ grub_net_recv_icmp6_packet (struct grub_net_buff
>> *nb,
>>               /* 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");
>>
>> @@ -429,12 +451,51 @@ grub_net_recv_icmp6_packet (struct grub_net_buff
>> *nb,
>>                 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 ("default6:%s", card->name);
> 
> It is usually <card>:<something-else>, not other way round. DHCPv4 sets
> default route to card:dhcp:default. May be card:ra:default6 to indicate
> auto-configuration.
> 
>> +        if (!name)
>> +          {
>> +        grub_errno = GRUB_ERR_NONE;
>> +        goto next;
>> +          }
>> +        /* Default routes take alll of the traffic, so make the mask
>> huge */
>                                      typo
> 
>> +        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;
>>         }
>> diff --git a/grub-core/net/net.c b/grub-core/net/net.c
>> index 21a4e94..65bea28 100644
>> --- a/grub-core/net/net.c
>> +++ b/grub-core/net/net.c
>> @@ -37,21 +37,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
>>
>>   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;
>> @@ -410,14 +395,6 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd
>> __attribute__ ((unused)),
>>     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)
>> @@ -524,6 +501,8 @@ match_net (const
>> grub_net_network_level_netaddress_t *net,
>>       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);
>> @@ -687,7 +666,14 @@ grub_net_route_address
>> (grub_net_network_level_address_t addr,
>>         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;
>>       }
>>
>> @@ -1109,7 +1095,8 @@ grub_net_add_route (const char *name,
>>   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)
> 
> This actually makes two functions rather redundant. But it is better
> merge them separately.
> 
>>   {
>>     struct grub_net_route *route;
>>
>> @@ -1127,6 +1114,7 @@ grub_net_add_route_gw (const char *name,
>>     route->target = target;
>>     route->is_gateway = 1;
>>     route->gw = gw;
>> +  route->interface = inter;
>>
>>     grub_net_route_register (route);
>>
>> @@ -1152,7 +1140,7 @@ grub_cmd_addroute (struct grub_command *cmd
>> __attribute__ ((unused)),
>>         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
>>       {
>> diff --git a/include/grub/net.h b/include/grub/net.h
>> index 4571b72..a1ff519 100644
>> --- a/include/grub/net.h
>> +++ b/include/grub/net.h
>> @@ -192,6 +192,18 @@ typedef struct grub_net_network_level_netaddress
>>     };
>>   } 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
>> @@ -368,6 +380,16 @@ grub_net_card_unregister (struct grub_net_card
>> *card);
>>   #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);
>>
>> @@ -393,7 +415,8 @@ grub_net_add_route (const char *name,
>>   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
>>
> 
> 
> _______________________________________________
> Grub-devel mailing list
> address@hidden
> https://lists.gnu.org/mailman/listinfo/grub-devel


Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]