]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
merge mine and abranches' branches. Fix several issues
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 24 Jun 2011 19:51:57 +0000 (21:51 +0200)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Fri, 24 Jun 2011 19:51:57 +0000 (21:51 +0200)
1  2 
grub-core/kern/file.c
grub-core/net/arp.c
grub-core/net/ethernet.c
grub-core/net/ip.c
grub-core/net/net.c
grub-core/net/tftp.c
grub-core/net/udp.c
include/grub/net.h

index 749e72dfc89b5f44497943dd84d8ff1bbaeb5ca1,749e72dfc89b5f44497943dd84d8ff1bbaeb5ca1..2407e72c5fb98603962e487bd8e10253d994f25d
@@@ -26,6 -26,6 +26,7 @@@
  #include <grub/device.h>
  
  grub_err_t (*grub_file_net_seek) (struct grub_file *file, grub_off_t offset) = NULL;
++void (*EXPORT_VAR (grub_grubnet_fini)) (void);
  
  grub_file_filter_t grub_file_filters_all[GRUB_FILE_FILTER_MAX];
  grub_file_filter_t grub_file_filters_enabled[GRUB_FILE_FILTER_MAX];
index 1dbd8a58f4f538cc0de7bd0e1b433eca1d04bff5,6fc7554cd69003b081485fe116d63630647066dc..fecde32824b05ee763770cf7e15524216de60fbd
@@@ -39,16 -39,9 +39,17 @@@ grub_net_arp_resolve (struct grub_net_n
    struct arphdr *arp_header;
    grub_net_link_level_address_t target_hw_addr;
    char *aux, arp_data[128];
+   grub_err_t err;
    int i;
  
 +  if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
 +      && proto_addr->ipv4 == 0xffffffff)
 +    {
 +      hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
 +      grub_memset (hw_addr->mac, -1, 6);
 +      return GRUB_ERR_NONE;
 +    }
 +
    /* Check cache table.  */
    entry = arp_find_entry (proto_addr);
    if (entry)
    nb.head = arp_data;
    nb.end = arp_data + sizeof (arp_data);
    grub_netbuff_clear (&nb);
    grub_netbuff_reserve (&nb, 128);
-   grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4));
 -  if ((err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4))) != GRUB_ERR_NONE)
++  err = grub_netbuff_push (&nb, sizeof (*arp_header) + 2 * (6 + 4));
++  if (err)
+     return err;
    arp_header = (struct arphdr *) nb.data;
    arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
    arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
index f1bc8c1d04edb80bb4a66a59dce53b4b5b3ee7d0,d33a07010fd0fb1df1e441fe7bab3701b9da960f..863e659a8afd2f6942a472072dae99090c27b1fb
@@@ -15,8 -15,10 +15,11 @@@ send_ethernet_packet (struct grub_net_n
                      grub_uint16_t ethertype)
  {
    struct etherhdr *eth;
+   grub_err_t err;
  
-   grub_netbuff_push (nb, sizeof (*eth));
 -  if ((err = grub_netbuff_push (nb, sizeof (*eth))) != GRUB_ERR_NONE)
++  err = grub_netbuff_push (nb, sizeof (*eth));
++  if (err)
+     return err;
    eth = (struct etherhdr *) nb->data;
    grub_memcpy (eth->dst, target_addr.mac, 6);
    grub_memcpy (eth->src, inf->hwaddress.mac, 6);
@@@ -34,11 -35,12 +37,14 @@@ grub_net_recv_ethernet_packet (struct g
    struct llchdr *llch;
    struct snaphdr *snaph;
    grub_uint16_t type;
 +  grub_net_link_level_address_t hwaddress;
+   grub_err_t err;
  
    eth = (struct etherhdr *) nb->data;
    type = grub_be_to_cpu16 (eth->type);
-   grub_netbuff_pull (nb, sizeof (*eth));
 -  if ((err = grub_netbuff_pull (nb, sizeof (*eth))) != GRUB_ERR_NONE)
++  err = grub_netbuff_pull (nb, sizeof (*eth));
++  if (err)
+     return err;
  
    if (type <= 1500)
      {
@@@ -47,7 -49,8 +53,9 @@@
  
        if (llch->dsap == 0xaa && llch->ssap == 0xaa && llch->ctrl == 0x3)
        {
-         grub_netbuff_pull (nb, sizeof (*llch));
 -        if ((err = grub_netbuff_pull (nb, sizeof (*llch))) != GRUB_ERR_NONE)
++        err = grub_netbuff_pull (nb, sizeof (*llch));
++        if (err)
+           return err;
          snaph = (struct snaphdr *) nb->data;
          type = snaph->type;
        }
index 808532a4a685d277b2593b2d830e5ae63d656416,749b41d02cb32bddd4d94d275a6bd6777520cd15..776937a6e277421efeeaa45edb8aa3ef2ea45f62
@@@ -65,42 -63,32 +65,44 @@@ grub_net_recv_ip_packets (struct grub_n
  {
    struct iphdr *iph = (struct iphdr *) nb->data;
    grub_err_t err;
 +  struct grub_net_network_level_interface *inf;
  
 -  if (nb->end - nb->data < (signed) sizeof (*iph))
 -    return 0;
 -  
 -  if (iph->protocol != 0x11 ||
 -      iph->dest != inf->address.ipv4)
 -    return 0;
 -
 -  grub_netbuff_pull (nb, sizeof (iph));
 -  err = grub_net_put_packet (&inf->nl_pending, nb);
 +  err = grub_netbuff_pull (nb, sizeof (*iph));
    if (err)
 +    return err;
 +
 +  FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
 +  {
 +    if (inf->card == card
 +      && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
 +      && inf->address.ipv4 == iph->dest
 +      && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
 +      break;
 +  }
 +  if (!inf)
      {
 -      grub_print_error ();
 -      return 0;
 +      FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
 +      if (inf->card == card
 +          && inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC
 +          && grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
 +      break;
 +    }
 +  if (!inf)
 +    {
 +      if (iph->protocol == IP_UDP
 +        && grub_net_hwaddr_cmp (&card->default_address, hwaddress) == 0)
 +      {
 +        struct udphdr *udph;
 +        udph = (struct udphdr *) nb->data;
-         grub_netbuff_pull (nb, sizeof (*udph));
++        err = grub_netbuff_pull (nb, sizeof (*udph));
++        if (err)
++          return err;
 +        if (grub_be_to_cpu16 (udph->dst) == 68)
 +          grub_net_process_dhcp (nb, card);
 +      }
 +      grub_netbuff_free (nb);
 +      return GRUB_ERR_NONE;
      }
 -  return 1;
 -}
 -*/
 -grub_err_t
 -grub_net_recv_ip_packets (struct grub_net_buff *nb)
 -{
 -  struct iphdr *iph = (struct iphdr *) nb->data;
 -  grub_err_t err;
 -
 -  if ((err = grub_netbuff_pull (nb, sizeof (*iph))) != GRUB_ERR_NONE)
 -    return err;
  
    switch (iph->protocol)
      {
index 2da60256c8a9ecbee95316b3a4c52fa0993901d8,c7732ecbf1e2156411b1e3aed5199184f79257fb..5c7d00991bfee90a7960413cc731e12e07adf5c1
@@@ -1100,130 -1021,14 +1110,139 @@@ grub_cmd_dhcpopt (struct grub_command *
                     "unrecognised format specification %s", args[3]);
  }
  
 +static grub_err_t
 +grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
 +              int argc, char **args)
 +{
 +  struct grub_net_card *card;
 +  struct grub_net_network_level_interface *ifaces;
 +  grub_size_t ncards = 0;
 +  unsigned j = 0;
 +  int interval;
 +  grub_err_t err;
 +
 +  FOR_NET_CARDS (card)
 +  {
 +    if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
 +      continue;
 +    ncards++;
 +  }
 +
 +  ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
 +  if (!ifaces)
 +    return grub_errno;
 +
 +  j = 0;
 +  FOR_NET_CARDS (card)
 +  {
 +    if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
 +      continue;
 +    ifaces[j].card = card;
 +    ifaces[j].next = &ifaces[j+1];
 +    if (j)
 +      ifaces[j].prev = &ifaces[j-1].next;
 +    ifaces[j].name = grub_xasprintf ("%s:dhcp_tmp", card->name);
 +    if (!ifaces[j].name)
 +      {
 +      unsigned i;
 +      for (i = 0; i < j; i++)
 +        grub_free (ifaces[i].name);
 +      grub_free (ifaces);
 +      return grub_errno;
 +      }
 +    ifaces[j].address.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_PROMISC;
 +    grub_memcpy (&ifaces[j].hwaddress, &card->default_address, 
 +               sizeof (ifaces[j].hwaddress));
 +    j++;
 +  }
 +  ifaces[ncards - 1].next = grub_net_network_level_interfaces;
 +  if (grub_net_network_level_interfaces)
 +    grub_net_network_level_interfaces->prev = & ifaces[ncards - 1].next;
 +  grub_net_network_level_interfaces = &ifaces[0];
 +  ifaces[0].prev = &grub_net_network_level_interfaces;
 +  for (interval = 200; interval < 10000; interval *= 2)
 +    {
 +      int done = 0;
 +      for (j = 0; j < ncards; j++)
 +      {
 +        struct grub_net_bootp_packet *pack;
 +        struct grub_datetime date;
 +        grub_int32_t t;
 +        struct grub_net_buff *nb;
 +        struct udphdr *udph;
 +        grub_net_network_level_address_t target;
 +
 +        if (!ifaces[j].prev)
 +          continue;
 +        nb = grub_netbuff_alloc (sizeof (*pack));
 +        if (!nb)
 +          return grub_errno;
 +        err = grub_netbuff_reserve (nb, sizeof (*pack) + 64 + 128);
 +        if (err)
 +          return err;
 +        err = grub_netbuff_push (nb, sizeof (*pack) + 64);
 +        if (err)
 +          return err;
 +        pack = (void *) nb->data;
 +        done = 1;
 +        grub_memset (pack, 0, sizeof (*pack) + 64);
 +        pack->opcode = 1;
 +        pack->hw_type = 1;
 +        pack->hw_len = 6;
 +        err = grub_get_datetime (&date);
 +        if (err || !grub_datetime2unixtime (&date, &t))
 +          {
 +            grub_errno = GRUB_ERR_NONE;
 +            t = 0;
 +          }
 +        pack->ident = grub_cpu_to_be32 (t);
 +        pack->seconds = 0;//grub_cpu_to_be16 (t);
 +
 +        grub_memcpy (&pack->mac_addr, &ifaces[j].hwaddress.mac, 6); 
 +
 +        grub_netbuff_push (nb, sizeof (*udph));
 +
 +        udph = (struct udphdr *) nb->data;
 +        udph->src = grub_cpu_to_be16 (68);
 +        udph->dst = grub_cpu_to_be16 (67);
 +        udph->chksum = 0;
 +        udph->len = grub_cpu_to_be16 (nb->tail - nb->data);
 +
 +        target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
 +        target.ipv4 = 0xffffffff;
 +
 +        err = grub_net_send_ip_packet (&ifaces[j], &target, nb);
 +        if (err)
 +          return err;
 +      }
 +      if (!done)
 +      break;
 +      grub_net_poll_cards (interval);
 +    }
 +
 +  err = GRUB_ERR_NONE;
 +  for (j = 0; j < ncards; j++)
 +    {
 +      if (!ifaces[j].prev)
 +      continue;
 +      grub_error_push ();
 +      grub_net_network_level_interface_unregister (&ifaces[j]);
 +      err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s",
 +                      ifaces[j].card->name);
 +    }
 +
 +  return err;
 +}
 +
+ static void
+ grub_grubnet_fini_real (void)
+ {
+   struct grub_net_card *card;
++
+   FOR_NET_CARDS (card)
+     if (card->driver)
+       card->driver->fini (card);
+ }
  
  static struct grub_fs grub_net_fs =
    {
index 545862092166265f9e051a096f0f83205a5ff249,138020b08681c8cdac92e3c814672d1ba5569f18..d0ed7c43a538fdd4eb889716d6e72a7b24f3f3d3
@@@ -154,8 -156,9 +156,10 @@@ tftp_receive (grub_net_socket_t sock, s
      }
    grub_netbuff_clear (&nb_ack);
    grub_netbuff_reserve (&nb_ack, 128);
-   grub_netbuff_push (&nb_ack, sizeof (tftph->opcode)
-                    + sizeof (tftph->u.ack.block));
 -  if ((err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode) 
 -                  + sizeof (tftph->u.ack.block))) != GRUB_ERR_NONE)
++  err = grub_netbuff_push (&nb_ack, sizeof (tftph->opcode)
++                         + sizeof (tftph->u.ack.block));
++  if (err)
+     return err;
  
    tftph = (struct tftphdr *) nb_ack.data;
    tftph->opcode = grub_cpu_to_be16 (TFTP_ACK);
index cc7534ea1aa375b2ae8449c566384a2fad55422b,b070cbb64a7f019cb09ee39e91d1d339377c1825..95134c0cfa2c37c4ca94f8103afa166328ce753d
@@@ -9,8 -9,10 +9,11 @@@ grub_net_send_udp_packet (const grub_ne
                          struct grub_net_buff *nb)
  {
    struct udphdr *udph;
+   grub_err_t err;
  
-   grub_netbuff_push (nb, sizeof (*udph));
 -  if ((err = grub_netbuff_push (nb, sizeof (*udph))) != GRUB_ERR_NONE)
++  err = grub_netbuff_push (nb, sizeof (*udph));
++  if (err)
+     return err;
  
    udph = (struct udphdr *) nb->data;
    udph->src = grub_cpu_to_be16 (socket->in_port);
index 5d99cace3811757d172c61195ec39327d5d0615e,006ec0686212f7e738fac2119ece2e2b91ae4acb..068ccec41c6e8b4584250d0badc76cba482352cb
@@@ -242,6 -239,7 +242,7 @@@ typedef struct grub_ne
  
  extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
  extern grub_err_t (*EXPORT_VAR (grub_file_net_seek)) (struct grub_file *file, grub_off_t offset);
 -void (*EXPORT_VAR (grub_grubnet_fini)) (void);
++extern void (*EXPORT_VAR (grub_grubnet_fini)) (void);
  
  struct grub_net_network_level_interface
  {