]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Added ARP protocol to network stack and fixed bug in grub_netbuff_alloc function.
authorPaulo de Rezende Pinatti <ppinatti@linux.vnet.ibm.com>
Fri, 13 Aug 2010 17:42:16 +0000 (14:42 -0300)
committerPaulo de Rezende Pinatti <ppinatti@linux.vnet.ibm.com>
Fri, 13 Aug 2010 17:42:16 +0000 (14:42 -0300)
* include/grub/net/arp.h: added arp header, arp cache entry and related constants and functions
* net/arp.c: added functions arp_init_table, arp_find_entry, arp_resolve and arp_receive
* net/ethernet.c (send_ethernet_packet): replaced hardcoded hardware address by parameter target_addr
* net/ethernet.c (recv_ethernet_packet): added call to arp_receive when packet is of type 0x803 (ARP) and only return when packet is of type determined by parameter ethertype
* net/ip.c (send_ip_packet): added call to arp_resolve to determine hardware address of destination
* net/netbuff.c (grub_netbuff_alloc): fixed swapped parameters in call to grub_memalign

12 files changed:
fs/ieee1275/ofnet.c
include/grub/net/arp.h
include/grub/net/interface.h
include/grub/net/ip.h
include/grub/net/protocol.h
net/arp.c
net/ethernet.c
net/interface.c
net/ip.c
net/netbuff.c
net/tftp.c
normal/misc.c

index 82b5235cc32d46261afe5ab70b07fa8e7ae73574..cf7eeb5b200efc7a23d39041548213729ebc63fc 100644 (file)
@@ -22,6 +22,7 @@
 #include <grub/disk.h>
 #include <grub/file.h>
 #include <grub/misc.h>
+#include <grub/net.h>
 #include <grub/net/arp.h>
 #include <grub/net/ip.h>
 #include <grub/net/udp.h>
@@ -95,7 +96,7 @@ retrieve_field(const char *src, char **field, const char **rest)
 static grub_err_t
 parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
 {
-  grub_uint32_t newip = 0;
+  grub_uint8_t *p = (grub_uint8_t *) ip;
   unsigned long t;
   int i;
   const char *ptr = val;
@@ -107,8 +108,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
        return grub_errno;
       if (t & ~0xff)
        return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
-      newip >>= 8;
-      newip |= (t << 24);
+      p[i] = (grub_uint8_t) t;
       if (i != 3 && *ptr != '.')
        return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
       ptr++;
@@ -116,7 +116,6 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
   ptr = ptr - 1;
   if ( *ptr != '\0' && *ptr != ',')
        return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
-  *ip = newip;
   if (rest)
     *rest = ptr;
   return 0;
@@ -305,12 +304,33 @@ grub_ofnetfs_open (struct grub_file *file , const char *name )
   char *datap;
   int amount = 0;
   grub_addr_t found_addr;
+  grub_netdisk_data_t netdisk_data = (grub_netdisk_data_t) file->device->disk->data;
+  // TODO: replace getting IP and MAC from bootp by routing functions
+  struct grub_net_network_layer_interface net_interface;
+  struct grub_net_card net_card;
+  struct grub_net_addr ila, lla;
+  ila.addr = (grub_uint8_t *) &(bootp_pckt->yiaddr);
+  ila.len = 4;
+  lla.addr = (grub_uint8_t *) &(bootp_pckt->chaddr);
+  lla.len = 6;
+  net_card.ila = &ila;
+  net_card.lla = &lla;
+  net_interface.card = &net_card;
+  // END TODO
+
+  if(! netdisk_data)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "arguments missing");
+
+  if(netdisk_data->protocol == GRUB_NETDISK_PROTOCOL_TFTP)
+    stack = grub_net_protocol_stack_get ("tftp");
+  else
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified");
 
-  stack = grub_net_protocol_stack_get ("tftp");
   app_interface = (struct grub_net_application_transport_interface *) stack->interface;
-  pack =  grub_netbuff_alloc (80*1024);
-  grub_netbuff_reserve (pack,80*1024);
-  file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name);
+  app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip);
+  pack =  grub_netbuff_alloc (2048);
+  grub_netbuff_reserve (pack,2048);
+  file_size = app_interface->app_prot->get_file_size(&net_interface,stack,pack,(char *) name);
 
   for (found_addr = 0x800000; found_addr <  + 2000 * 0x100000; found_addr += 0x100000)
   {
@@ -320,16 +340,16 @@ grub_ofnetfs_open (struct grub_file *file , const char *name )
   file->data = (void *) found_addr;
 
   grub_netbuff_clear(pack); 
-  grub_netbuff_reserve (pack,80*1024);
-  app_interface->app_prot->open (NULL,stack,pack,(char *) name);
+  grub_netbuff_reserve (pack,2048);
+  app_interface->app_prot->open (&net_interface,stack,pack,(char *) name);
   if (grub_errno != GRUB_ERR_NONE)
     goto error;
   
   do 
   {  
     grub_netbuff_clear(pack); 
-    grub_netbuff_reserve (pack,80*1024);
-    app_interface->app_prot->recv (NULL,stack,pack); 
+    grub_netbuff_reserve (pack,2048);
+    app_interface->app_prot->recv (&net_interface,stack,pack); 
     if (grub_errno != GRUB_ERR_NONE)
       goto error;
     if ((pack->tail - pack->data))
@@ -340,8 +360,8 @@ grub_ofnetfs_open (struct grub_file *file , const char *name )
       grub_memcpy(datap , pack->data, pack->tail - pack->data); 
     }
     grub_netbuff_clear(pack); 
-    grub_netbuff_reserve (pack,80*1024);
-    app_interface->app_prot->send_ack (NULL,stack,pack); 
+    grub_netbuff_reserve (pack,2048);
+    app_interface->app_prot->send_ack (&net_interface,stack,pack); 
 
     if (grub_errno != GRUB_ERR_NONE)
       goto error;
index 86ae2deea640931060502afc587c9f92a69b4df7..75260aeb3923da9962b5e2f35032cf87a4763c07 100644 (file)
@@ -1,17 +1,42 @@
 #ifndef GRUB_NET_ARP_HEADER
 #define GRUB_NET_ARP_HEADER    1
+#include <grub/misc.h>
+#include <grub/net.h>
+#include <grub/net/protocol.h>
 
-#include <grub/net/ethernet.h>
-struct arphdr{
-    grub_int16_t hwtype;        /* hardware type (must be ARPHRD_ETHER) */
-    grub_int16_t protocol;      /* protocol type (must be ETH_P_IP) */
-    grub_int8_t hwlen;            /* hardware address length (must be 6) */
-    grub_int8_t protolen;         /* protocol address length (must be 4) */
-    grub_uint16_t opcode;        /* ARP opcode */
-    grub_uint8_t shwaddr[6];     /* sender's hardware address */
-    grub_uint32_t sipaddr;     /* sender's IP address */
-    grub_uint8_t thwaddr[6];     /* target's hardware address */
-    grub_uint32_t tipaddr;     /* target's IP address */
-}__attribute__ ((packed));
+/* IANA ARP constant to define hardware type as ethernet */
+#define ARPHRD_ETHERNET 1
+/* IANA Ethertype */
+#define ARP_ETHERTYPE 0x806
+
+/* Size for cache table */
+#define SIZE_ARP_TABLE 5
+
+/* ARP header operation codes */
+#define ARP_REQUEST 1
+#define ARP_REPLY 2
+
+struct arp_entry {
+    grub_uint8_t avail;
+    struct grub_net_network_layer_protocol *nl_protocol;
+    struct grub_net_link_layer_protocol *ll_protocol;
+    struct grub_net_addr nl_address;
+    struct grub_net_addr ll_address;
+};
+
+struct arphdr {
+  grub_uint16_t hrd;
+  grub_uint16_t pro;
+  grub_uint8_t hln;
+  grub_uint8_t pln;
+  grub_uint16_t op;
+} __attribute__ ((packed));
+
+extern grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
+struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb);
+
+extern grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), 
+struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, 
+struct grub_net_addr *hw_addr);
 
 #endif 
index 4d100fd75c1b88de9b94c195e93f43ecda79e03f..cf24dd22e4dccd0860d3a96692cc54ae951210de 100644 (file)
@@ -37,7 +37,7 @@ struct grub_net_network_link_interface
 };
 
 
-extern struct grub_net_protocol_stack *grub_net_protocol_stacks;
+struct grub_net_protocol_stack *grub_net_protocol_stacks;
 static inline void
 grub_net_stack_register (struct grub_net_protocol_stack *stack)
 {
index cb119ac6f7064d42c072b51a51848b1a1e402a32..5baacd439d6514fb2735129fad7c4c70565a4fac 100644 (file)
@@ -2,6 +2,7 @@
 #define GRUB_NET_IP_HEADER     1
 #include <grub/misc.h>
 
+#define IP_ETHERTYPE 0x800 /* IANA Ethertype */
 
 struct iphdr {
   grub_uint8_t verhdrlen;
index b7a3e5d3b33f5ccf80373beeffb8995000b03267..ffc3dd719f25f767feb8015eac47dede49100505 100644 (file)
@@ -8,7 +8,7 @@
 struct grub_net_protocol;
 struct grub_net_protocol_stack;
 struct grub_net_network_layer_interface;
-
+struct grub_net_addr;
 
 typedef enum grub_network_layer_protocol_id 
 {
@@ -57,6 +57,7 @@ struct grub_net_network_layer_protocol
   struct grub_net_network_layer_protocol *next;
   char *name;
   grub_net_protocol_id_t id;
+  grub_uint16_t type; /* IANA Ethertype */
   //grub_network_layer_protocol_id_t id;
   grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr);
   char * (*aton) (union grub_net_network_layer_address addr);
@@ -76,11 +77,14 @@ struct grub_net_link_layer_protocol
   
   struct grub_net_link_layer_protocol *next;
   char *name;
+  grub_uint16_t type; /* ARP hardware type */
   grub_net_protocol_id_t id;
   grub_err_t (*send) (struct grub_net_network_layer_interface *inf ,
-             struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb);
+             struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb,
+             struct grub_net_addr target_addr, grub_uint16_t ethertype);
   grub_err_t (*recv) (struct grub_net_network_layer_interface *inf ,
-             struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb);
+             struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb,
+             grub_uint16_t ethertype);
 };
 
 extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols;
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c02ea011d10c3a6afaed429dfb4f369e5668de4a 100644 (file)
--- a/net/arp.c
+++ b/net/arp.c
@@ -0,0 +1,207 @@
+#include <grub/net/arp.h>
+#include <grub/net/netbuff.h>
+#include <grub/net/interface.h>
+#include <grub/mm.h>
+#include <grub/net.h>
+#include <grub/net/ethernet.h>
+#include <grub/net/ip.h>
+#include <grub/time.h>
+#include <grub/net/ieee1275/interface.h>
+
+static struct arp_entry arp_table[SIZE_ARP_TABLE];
+static grub_int8_t new_table_entry = -1;
+
+static void arp_init_table(void)
+{
+  struct arp_entry *entry = &(arp_table[0]);
+  for(;entry<=&(arp_table[SIZE_ARP_TABLE-1]);entry++)
+    {
+      entry->avail = 0;
+      entry->nl_protocol = NULL;
+      entry->ll_protocol = NULL;
+      entry->nl_address.addr = NULL;
+      entry->nl_address.len = 0;
+      entry->ll_address.addr = NULL;
+      entry->ll_address.len = 0;
+    }
+  new_table_entry = 0;
+}
+
+static struct arp_entry *
+arp_find_entry(struct grub_net_network_link_interface *net_link_inf, const void *proto_address, grub_uint8_t address_len)
+{
+  grub_uint8_t i;
+  for(i=0;i < SIZE_ARP_TABLE; i++)
+    {
+      if(arp_table[i].avail == 1 && 
+         arp_table[i].nl_protocol->type == net_link_inf->net_prot->type && 
+         arp_table[i].ll_protocol->type == net_link_inf->link_prot->type &&
+         (!grub_memcmp(arp_table[i].nl_address.addr, proto_address, address_len)))
+        return &(arp_table[i]);
+    }
+  return NULL;
+}
+
+grub_err_t arp_resolve(struct grub_net_network_layer_interface *inf __attribute__ ((unused)), 
+struct grub_net_network_link_interface *net_link_inf, struct grub_net_addr *proto_addr, 
+struct grub_net_addr *hw_addr)
+{
+  struct arp_entry *entry;
+  struct grub_net_buff *nb;
+  struct arphdr *arp_header;
+  struct grub_net_addr target_hw_addr;
+  grub_uint8_t *aux, i;
+
+  /* Check cache table */
+  entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len);
+  if (entry)
+    {
+      hw_addr->addr = grub_malloc(entry->ll_address.len);
+      if (! hw_addr->addr)
+        return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+      grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len);
+      hw_addr->len = entry->ll_address.len;
+      return GRUB_ERR_NONE;
+    }
+  /* Build a request packet */
+  nb = grub_netbuff_alloc (2048);
+  grub_netbuff_reserve(nb, 2048);
+  grub_netbuff_push(nb, sizeof(*arp_header) + 2*(inf->card->lla->len + inf->card->ila->len));
+  arp_header = (struct arphdr *)nb->data;
+  arp_header->hrd = net_link_inf->link_prot->type;
+  arp_header->pro = net_link_inf->net_prot->type;
+  arp_header->hln = inf->card->lla->len;
+  arp_header->pln = inf->card->ila->len;
+  arp_header->op = ARP_REQUEST;
+  aux = (grub_uint8_t *)arp_header + sizeof(*arp_header);
+  /* Sender hardware address */
+  grub_memcpy(aux, inf->card->lla->addr, inf->card->lla->len);
+  aux += inf->card->lla->len;
+  /* Sender protocol address */
+  grub_memcpy(aux, inf->card->ila->addr, inf->card->ila->len);
+  aux += inf->card->ila->len;
+  /* Target hardware address */
+  for(i=0; i < inf->card->lla->len; i++)
+    aux[i] = 0x00;
+  aux += inf->card->lla->len;
+  /* Target protocol address */
+  grub_memcpy(aux, proto_addr->addr, inf->card->ila->len);
+
+  target_hw_addr.addr = grub_malloc(inf->card->lla->len);
+  target_hw_addr.len = inf->card->lla->len;
+  for(i=0; i < target_hw_addr.len; i++)
+    (target_hw_addr.addr)[i] = 0xFF;
+  net_link_inf->link_prot->send(inf, net_link_inf, nb, target_hw_addr, ARP_ETHERTYPE);
+  grub_free(target_hw_addr.addr);
+  grub_netbuff_clear(nb); 
+  grub_netbuff_reserve(nb, 2048);
+
+  grub_uint64_t start_time, current_time;
+  start_time = grub_get_time_ms();
+  do
+    {
+      net_link_inf->link_prot->recv(inf, net_link_inf, nb, ARP_ETHERTYPE);
+      /* Now check cache table again */
+      entry = arp_find_entry(net_link_inf, proto_addr->addr, proto_addr->len);
+      if (entry)
+        {
+          hw_addr->addr = grub_malloc(entry->ll_address.len);
+          if (! hw_addr->addr)
+            return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+          grub_memcpy(hw_addr->addr, entry->ll_address.addr, entry->ll_address.len);
+          hw_addr->len = entry->ll_address.len;
+          grub_netbuff_clear(nb); 
+          return GRUB_ERR_NONE;
+        }
+      current_time =  grub_get_time_ms();
+      if (current_time -  start_time > TIMEOUT_TIME_MS)
+        break;
+    } while (! entry);
+  grub_netbuff_clear(nb); 
+  return grub_error (GRUB_ERR_TIMEOUT, "Timeout: could not resolve hardware address.");
+}
+
+grub_err_t arp_receive(struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
+struct grub_net_network_link_interface *net_link_inf, struct grub_net_buff *nb)
+{
+  struct arphdr *arp_header = (struct arphdr *)nb->data;
+  struct arp_entry *entry;
+  grub_uint8_t merge = 0;
+
+  /* Verify hardware type, protocol type, hardware address length, protocol address length */
+  if (arp_header->hrd != net_link_inf->link_prot->type || arp_header->pro != net_link_inf->net_prot->type ||
+      arp_header->hln != inf->card->lla->len || arp_header->pln != inf->card->ila->len)
+    return GRUB_ERR_NONE;
+
+  grub_uint8_t *sender_hardware_address, *sender_protocol_address, *target_hardware_address, *target_protocol_address;
+  sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header);
+  sender_protocol_address = sender_hardware_address + arp_header->hln;
+  target_hardware_address = sender_protocol_address + arp_header->pln;
+  target_protocol_address = target_hardware_address + arp_header->hln;
+  /* Check if the sender is in the cache table */
+  entry = arp_find_entry(net_link_inf, sender_protocol_address, arp_header->pln);
+  /* Update sender hardware address */
+  if (entry)
+    {
+      if (entry->ll_address.addr)
+        grub_free(entry->ll_address.addr);
+      entry->ll_address.addr = grub_malloc(arp_header->hln);
+      if (! entry->ll_address.addr)
+        return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+      grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln);
+      entry->ll_address.len = arp_header->hln;
+      merge = 1;
+    }
+  /* Am I the protocol address target? */
+  if (! grub_memcmp(target_protocol_address, inf->card->ila->addr, arp_header->pln))
+    {
+    /* Add sender to cache table */
+    if (! merge)
+      {
+      if (new_table_entry == -1)
+        arp_init_table();
+      entry = &(arp_table[new_table_entry]);
+      entry->avail = 1;
+      entry->ll_protocol = net_link_inf->link_prot;
+      entry->nl_protocol = net_link_inf->net_prot;
+      if (entry->nl_address.addr)
+        grub_free(entry->nl_address.addr);
+      entry->nl_address.addr = grub_malloc(arp_header->pln);
+      if (! entry->nl_address.addr)
+        return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+      grub_memcpy(entry->nl_address.addr, sender_protocol_address, arp_header->pln);
+      entry->nl_address.len = arp_header->pln;
+      if (entry->ll_address.addr)
+        grub_free(entry->ll_address.addr);
+      entry->ll_address.addr = grub_malloc(arp_header->hln);
+      if (! entry->ll_address.addr)
+        return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+      grub_memcpy(entry->ll_address.addr, sender_hardware_address, arp_header->hln);
+      entry->ll_address.len = arp_header->hln;
+      new_table_entry++;
+      if (new_table_entry == SIZE_ARP_TABLE)
+        new_table_entry = 0;
+      }
+    if (arp_header->op == ARP_REQUEST)
+      {
+        struct grub_net_addr aux;
+        /* Swap hardware fields */
+        grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln);
+        grub_memcpy(sender_hardware_address, inf->card->lla->addr, arp_header->hln);
+        /* Swap protocol fields */
+        aux.addr = grub_malloc(arp_header->pln);
+        if (! aux.addr)
+          return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+        grub_memcpy(aux.addr, sender_protocol_address, arp_header->pln);
+        grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln);
+        grub_memcpy(target_protocol_address, aux.addr, arp_header->pln);
+        grub_free(aux.addr);
+        /* Change operation to REPLY and send packet */
+        arp_header->op = ARP_REPLY;
+        aux.addr = target_hardware_address;
+        aux.len = arp_header->hln;
+        net_link_inf->link_prot->send(inf, net_link_inf, nb, aux, ARP_ETHERTYPE);
+      }
+    }
+  return GRUB_ERR_NONE;
+}
index ab5992133645510903f022237fc5f62445391588..14bc41c5b661dc4a0bb4a140c69c7b501ece5c92 100644 (file)
@@ -8,24 +8,21 @@
 #include <grub/net/interface.h>
 #include <grub/net.h>
 #include <grub/time.h>
+#include <grub/net/arp.h>
 
 static grub_err_t 
 send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
-   struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb)
+struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb,
+struct grub_net_addr target_addr, grub_uint16_t ethertype)
 {
 
   struct etherhdr *eth; 
    
   grub_netbuff_push (nb,sizeof(*eth));
   eth = (struct etherhdr *) nb->data; 
-  eth->dst[0] = 0x00;
-  eth->dst[1] = 0x11;
-  eth->dst[2] = 0x25;
-  eth->dst[3] = 0xca;
-  eth->dst[4] = 0x1f;
-  eth->dst[5] = 0x01;
-  grub_memcpy (eth->src, bootp_pckt -> chaddr,6);
-  eth->type = 0x0800;
+  grub_memcpy(eth->dst, target_addr.addr, target_addr.len);
+  grub_memcpy(eth->src, bootp_pckt->chaddr, 6);
+  eth->type = ethertype;
 
   return  send_card_buffer(nb);  
 //  return  inf->card->driver->send(inf->card,nb);
@@ -34,7 +31,8 @@ send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__
 
 static grub_err_t 
 recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
-   struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb)
+struct grub_net_network_link_interface *net_link_inf __attribute__ ((unused)) ,struct grub_net_buff *nb,
+grub_uint16_t ethertype)
 {
   struct etherhdr *eth;
   grub_uint64_t start_time, current_time;
@@ -63,12 +61,17 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__
       }
     }
 
-   /*change for grub_memcmp*/
-   //if( eth->src[0] == 0x00 &&  eth->src[1] == 0x11 &&  eth->src[2] == 0x25 && 
-     //          eth->src[3] == 0xca &&  eth->src[4] == 0x1f &&  eth->src[5] == 0x01 && type == 0x800)
-   if(type == 0x800) 
-     return 0;
-   
+    /* ARP packet */
+    if (type == ARP_ETHERTYPE)
+    {
+       arp_receive(inf, net_link_inf, nb);
+       if (ethertype == ARP_ETHERTYPE)
+        return GRUB_ERR_NONE;
+    }
+    /* IP packet */
+    else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE)
+      return GRUB_ERR_NONE;
+
     current_time =  grub_get_time_ms ();
     if (current_time -  start_time > TIMEOUT_TIME_MS)
       return grub_error (GRUB_ERR_TIMEOUT, "Time out.");
@@ -77,7 +80,7 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__
   - verify if the next layer is the desired one.
      - if not. get another packet.
   - remove ethernet header from buffer*/
-  return 0
+  return GRUB_ERR_NONE
 }
 
 
@@ -85,6 +88,7 @@ static struct grub_net_link_layer_protocol grub_ethernet_protocol =
 {
   .name = "ethernet",
   .id = GRUB_NET_ETHERNET_ID,
+  .type = ARPHRD_ETHERNET,
   .send = send_ethernet_packet,
   .recv = recv_ethernet_packet 
 };
index bacabf4cb95d3e6edcaf91df94753498412fe0c3..f17b3e66b1b6303ad4ca9f36468a7f77998668b0 100644 (file)
@@ -22,7 +22,6 @@ INTERFACE_REGISTER_FUNCTIONS("link");*/
 
 #include <grub/mm.h>
 #include <grub/net/interface.h>
-struct grub_net_protocol_stack *grub_net_protocol_stacks;
 struct grub_net_protocol_stack 
   *grub_net_protocol_stack_get (char *name)
 {
index 65b0f2b707a00a74bdf9b5505a1882f084493c24..142f33e70335a64312dd897136de7c73586bde23 100644 (file)
--- a/net/ip.c
+++ b/net/ip.c
@@ -1,6 +1,7 @@
 #include <grub/net/ip.h>
 #include <grub/net/ieee1275/interface.h>
 #include <grub/misc.h>
+#include <grub/net/arp.h>
 #include <grub/net/ethernet.h>
 #include <grub/net/interface.h>
 #include <grub/net/type_net.h>
@@ -36,6 +37,8 @@ send_ip_packet (struct grub_net_network_layer_interface *inf,
   
   struct iphdr *iph;
   static int id = 0x2400; 
+  struct grub_net_addr nl_target_addr, ll_target_addr;
+  grub_err_t rc;
   
   grub_netbuff_push(nb,sizeof(*iph)); 
   iph = (struct iphdr *) nb->data;   
@@ -51,12 +54,26 @@ send_ip_packet (struct grub_net_network_layer_interface *inf,
   iph->ttl = 0xff;
   iph->protocol = 0x11;
   iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr);
-  iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr);
+  // iph->dest = (grub_uint32_t) bootp_pckt -> siaddr;//inf->address.ipv4;// *((grub_uint32_t *)inf->ila->addr);
+  iph->dest = *((grub_uint32_t *) (trans_net_inf->data));
   
   iph->chksum = 0 ;
   iph->chksum = ipchksum((void *)nb->data, sizeof(*iph));
   
-  return trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb);
+  /* Determine link layer target address via ARP */
+  nl_target_addr.len = sizeof(iph->dest);
+  nl_target_addr.addr = grub_malloc(nl_target_addr.len);
+  if (! nl_target_addr.addr)
+    return grub_error (GRUB_ERR_OUT_OF_MEMORY, "fail to alloc memory");
+  grub_memcpy(nl_target_addr.addr, &(iph->dest), nl_target_addr.len);
+  rc = arp_resolve(inf, trans_net_inf->inner_layer, &nl_target_addr, &ll_target_addr);
+  grub_free(nl_target_addr.addr);
+  if (rc != GRUB_ERR_NONE)
+    return rc;
+
+  rc = trans_net_inf->inner_layer->link_prot->send(inf,trans_net_inf->inner_layer,nb,ll_target_addr, IP_ETHERTYPE);
+  grub_free(ll_target_addr.addr);
+  return rc;
   //return protstack->next->prot->send(inf,protstack->next,nb); 
 }
 
@@ -70,11 +87,12 @@ recv_ip_packet (struct grub_net_network_layer_interface *inf,
   start_time = grub_get_time_ms();
   while (1)
   {
-    trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb);
+    trans_net_inf->inner_layer->link_prot->recv(inf,trans_net_inf->inner_layer,nb,IP_ETHERTYPE);
     iph = (struct iphdr *) nb->data;
     if (iph->protocol == 0x11 &&
            iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr && 
-           iph->src ==  (grub_uint32_t) bootp_pckt -> siaddr )
+           //iph->src ==  (grub_uint32_t) bootp_pckt -> siaddr )
+           iph->src ==  *((grub_uint32_t *) (trans_net_inf->data)) )
     {
       grub_netbuff_pull(nb,sizeof(*iph));
       return 0; 
@@ -99,6 +117,7 @@ static struct grub_net_network_layer_protocol grub_ipv4_protocol =
 {
  .name = "ipv4",
  .id = GRUB_NET_IPV4_ID,
+ .type = IP_ETHERTYPE,
  .send = send_ip_packet,
  .recv = recv_ip_packet
 };
index ce52233b6554f6cca6480cdc5486fabdcbd77a64..4f6a1da84b3c6cf5a45bc73a8d6f4a42d7544122 100644 (file)
@@ -72,7 +72,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len )
     len = NETBUFFMINLEN;
   
   len = ALIGN_UP (len,NETBUFF_ALIGN);
-  data = grub_memalign (len + sizeof (*nb),NETBUFF_ALIGN); 
+  data = grub_memalign (NETBUFF_ALIGN, len + sizeof (*nb));
   nb = (struct grub_net_buff *) ((int)data + len); 
   nb->head = nb->data = nb->tail = data;
   nb->end = (char *) nb; 
index 0fb43105d94bb3108f86ab6f31d7431e4b8796a4..2aeae38e969e40802b6891fb25898a8e4a5fd2a8 100644 (file)
@@ -113,7 +113,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)),
   app_interface->trans_prot->send (inf,protstack->interface,nb);
   /*Receive OACK*/
   grub_netbuff_clear (nb); 
-  grub_netbuff_reserve (nb,80*1024);
+  grub_netbuff_reserve (nb,2048);
   return app_interface->app_prot->recv(inf,protstack,nb);
 }
 
@@ -215,7 +215,7 @@ static int tftp_file_size (struct grub_net_network_layer_interface* inf ,
 
   tftp_open (inf, protocol_stack,nb, filename);
   grub_netbuff_clear (nb); 
-  grub_netbuff_reserve (nb,80*1024);
+  grub_netbuff_reserve (nb,2048);
   tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0);
 
   return tftp_file.size;
index d53fe711c84dce040655602d752386cb69907a70..30967e174a536470e93f1543a16e63b0fce69d5b 100644 (file)
@@ -54,7 +54,7 @@ grub_normal_print_device_info (const char *name)
             grub_printf_(N_("Protocol: %s"), "Unknown"); 
           grub_putchar ('\n');
           grub_putchar ('\t');
-          grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip & 0xff, data->server_ip >> 8 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 24 & 0xff); 
+          grub_printf_(N_("Server IP: %d.%d.%d.%d"), data->server_ip >> 24 & 0xff, data->server_ip >> 16 & 0xff, data->server_ip >> 8 & 0xff, data->server_ip & 0xff); 
           if (data->username)
             {
               grub_putchar ('\n');