Added ARP protocol to network stack and fixed bug in grub_netbuff_alloc function.
* 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
This commit is contained in:
parent
7c978f0690
commit
10830203a0
12 changed files with 335 additions and 56 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include <grub/disk.h>
|
#include <grub/disk.h>
|
||||||
#include <grub/file.h>
|
#include <grub/file.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net.h>
|
||||||
#include <grub/net/arp.h>
|
#include <grub/net/arp.h>
|
||||||
#include <grub/net/ip.h>
|
#include <grub/net/ip.h>
|
||||||
#include <grub/net/udp.h>
|
#include <grub/net/udp.h>
|
||||||
|
@ -95,7 +96,7 @@ retrieve_field(const char *src, char **field, const char **rest)
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
|
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;
|
unsigned long t;
|
||||||
int i;
|
int i;
|
||||||
const char *ptr = val;
|
const char *ptr = val;
|
||||||
|
@ -107,8 +108,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
if (t & ~0xff)
|
if (t & ~0xff)
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
||||||
newip >>= 8;
|
p[i] = (grub_uint8_t) t;
|
||||||
newip |= (t << 24);
|
|
||||||
if (i != 3 && *ptr != '.')
|
if (i != 3 && *ptr != '.')
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
||||||
ptr++;
|
ptr++;
|
||||||
|
@ -116,7 +116,6 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
|
||||||
ptr = ptr - 1;
|
ptr = ptr - 1;
|
||||||
if ( *ptr != '\0' && *ptr != ',')
|
if ( *ptr != '\0' && *ptr != ',')
|
||||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
return grub_error (GRUB_ERR_OUT_OF_RANGE, "Invalid IP.");
|
||||||
*ip = newip;
|
|
||||||
if (rest)
|
if (rest)
|
||||||
*rest = ptr;
|
*rest = ptr;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -305,12 +304,33 @@ grub_ofnetfs_open (struct grub_file *file , const char *name )
|
||||||
char *datap;
|
char *datap;
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
grub_addr_t found_addr;
|
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");
|
stack = grub_net_protocol_stack_get ("tftp");
|
||||||
|
else
|
||||||
|
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid protocol specified");
|
||||||
|
|
||||||
app_interface = (struct grub_net_application_transport_interface *) stack->interface;
|
app_interface = (struct grub_net_application_transport_interface *) stack->interface;
|
||||||
pack = grub_netbuff_alloc (80*1024);
|
app_interface->inner_layer->data = (void *) &(netdisk_data->server_ip);
|
||||||
grub_netbuff_reserve (pack,80*1024);
|
pack = grub_netbuff_alloc (2048);
|
||||||
file_size = app_interface->app_prot->get_file_size(NULL,stack,pack,(char *) name);
|
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)
|
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;
|
file->data = (void *) found_addr;
|
||||||
|
|
||||||
grub_netbuff_clear(pack);
|
grub_netbuff_clear(pack);
|
||||||
grub_netbuff_reserve (pack,80*1024);
|
grub_netbuff_reserve (pack,2048);
|
||||||
app_interface->app_prot->open (NULL,stack,pack,(char *) name);
|
app_interface->app_prot->open (&net_interface,stack,pack,(char *) name);
|
||||||
if (grub_errno != GRUB_ERR_NONE)
|
if (grub_errno != GRUB_ERR_NONE)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
grub_netbuff_clear(pack);
|
grub_netbuff_clear(pack);
|
||||||
grub_netbuff_reserve (pack,80*1024);
|
grub_netbuff_reserve (pack,2048);
|
||||||
app_interface->app_prot->recv (NULL,stack,pack);
|
app_interface->app_prot->recv (&net_interface,stack,pack);
|
||||||
if (grub_errno != GRUB_ERR_NONE)
|
if (grub_errno != GRUB_ERR_NONE)
|
||||||
goto error;
|
goto error;
|
||||||
if ((pack->tail - pack->data))
|
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_memcpy(datap , pack->data, pack->tail - pack->data);
|
||||||
}
|
}
|
||||||
grub_netbuff_clear(pack);
|
grub_netbuff_clear(pack);
|
||||||
grub_netbuff_reserve (pack,80*1024);
|
grub_netbuff_reserve (pack,2048);
|
||||||
app_interface->app_prot->send_ack (NULL,stack,pack);
|
app_interface->app_prot->send_ack (&net_interface,stack,pack);
|
||||||
|
|
||||||
if (grub_errno != GRUB_ERR_NONE)
|
if (grub_errno != GRUB_ERR_NONE)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
@ -1,17 +1,42 @@
|
||||||
#ifndef GRUB_NET_ARP_HEADER
|
#ifndef GRUB_NET_ARP_HEADER
|
||||||
#define GRUB_NET_ARP_HEADER 1
|
#define GRUB_NET_ARP_HEADER 1
|
||||||
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net.h>
|
||||||
|
#include <grub/net/protocol.h>
|
||||||
|
|
||||||
#include <grub/net/ethernet.h>
|
/* IANA ARP constant to define hardware type as ethernet */
|
||||||
struct arphdr{
|
#define ARPHRD_ETHERNET 1
|
||||||
grub_int16_t hwtype; /* hardware type (must be ARPHRD_ETHER) */
|
/* IANA Ethertype */
|
||||||
grub_int16_t protocol; /* protocol type (must be ETH_P_IP) */
|
#define ARP_ETHERTYPE 0x806
|
||||||
grub_int8_t hwlen; /* hardware address length (must be 6) */
|
|
||||||
grub_int8_t protolen; /* protocol address length (must be 4) */
|
/* Size for cache table */
|
||||||
grub_uint16_t opcode; /* ARP opcode */
|
#define SIZE_ARP_TABLE 5
|
||||||
grub_uint8_t shwaddr[6]; /* sender's hardware address */
|
|
||||||
grub_uint32_t sipaddr; /* sender's IP address */
|
/* ARP header operation codes */
|
||||||
grub_uint8_t thwaddr[6]; /* target's hardware address */
|
#define ARP_REQUEST 1
|
||||||
grub_uint32_t tipaddr; /* target's IP address */
|
#define ARP_REPLY 2
|
||||||
}__attribute__ ((packed));
|
|
||||||
|
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
|
#endif
|
||||||
|
|
|
@ -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
|
static inline void
|
||||||
grub_net_stack_register (struct grub_net_protocol_stack *stack)
|
grub_net_stack_register (struct grub_net_protocol_stack *stack)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define GRUB_NET_IP_HEADER 1
|
#define GRUB_NET_IP_HEADER 1
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
|
||||||
|
#define IP_ETHERTYPE 0x800 /* IANA Ethertype */
|
||||||
|
|
||||||
struct iphdr {
|
struct iphdr {
|
||||||
grub_uint8_t verhdrlen;
|
grub_uint8_t verhdrlen;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
struct grub_net_protocol;
|
struct grub_net_protocol;
|
||||||
struct grub_net_protocol_stack;
|
struct grub_net_protocol_stack;
|
||||||
struct grub_net_network_layer_interface;
|
struct grub_net_network_layer_interface;
|
||||||
|
struct grub_net_addr;
|
||||||
|
|
||||||
typedef enum grub_network_layer_protocol_id
|
typedef enum grub_network_layer_protocol_id
|
||||||
{
|
{
|
||||||
|
@ -57,6 +57,7 @@ struct grub_net_network_layer_protocol
|
||||||
struct grub_net_network_layer_protocol *next;
|
struct grub_net_network_layer_protocol *next;
|
||||||
char *name;
|
char *name;
|
||||||
grub_net_protocol_id_t id;
|
grub_net_protocol_id_t id;
|
||||||
|
grub_uint16_t type; /* IANA Ethertype */
|
||||||
//grub_network_layer_protocol_id_t id;
|
//grub_network_layer_protocol_id_t id;
|
||||||
grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr);
|
grub_err_t (*ntoa) (char *name, grub_net_network_layer_address_t *addr);
|
||||||
char * (*aton) (union grub_net_network_layer_address 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;
|
struct grub_net_link_layer_protocol *next;
|
||||||
char *name;
|
char *name;
|
||||||
|
grub_uint16_t type; /* ARP hardware type */
|
||||||
grub_net_protocol_id_t id;
|
grub_net_protocol_id_t id;
|
||||||
grub_err_t (*send) (struct grub_net_network_layer_interface *inf ,
|
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 ,
|
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;
|
extern struct grub_net_network_layer_protocol *grub_net_network_layer_protocols;
|
||||||
|
|
207
net/arp.c
207
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;
|
||||||
|
}
|
|
@ -8,24 +8,21 @@
|
||||||
#include <grub/net/interface.h>
|
#include <grub/net/interface.h>
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
#include <grub/time.h>
|
#include <grub/time.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
send_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
|
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;
|
struct etherhdr *eth;
|
||||||
|
|
||||||
grub_netbuff_push (nb,sizeof(*eth));
|
grub_netbuff_push (nb,sizeof(*eth));
|
||||||
eth = (struct etherhdr *) nb->data;
|
eth = (struct etherhdr *) nb->data;
|
||||||
eth->dst[0] = 0x00;
|
grub_memcpy(eth->dst, target_addr.addr, target_addr.len);
|
||||||
eth->dst[1] = 0x11;
|
grub_memcpy(eth->src, bootp_pckt->chaddr, 6);
|
||||||
eth->dst[2] = 0x25;
|
eth->type = ethertype;
|
||||||
eth->dst[3] = 0xca;
|
|
||||||
eth->dst[4] = 0x1f;
|
|
||||||
eth->dst[5] = 0x01;
|
|
||||||
grub_memcpy (eth->src, bootp_pckt -> chaddr,6);
|
|
||||||
eth->type = 0x0800;
|
|
||||||
|
|
||||||
return send_card_buffer(nb);
|
return send_card_buffer(nb);
|
||||||
// return inf->card->driver->send(inf->card,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
|
static grub_err_t
|
||||||
recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__ ((unused)),
|
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;
|
struct etherhdr *eth;
|
||||||
grub_uint64_t start_time, current_time;
|
grub_uint64_t start_time, current_time;
|
||||||
|
@ -63,11 +61,16 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*change for grub_memcmp*/
|
/* ARP packet */
|
||||||
//if( eth->src[0] == 0x00 && eth->src[1] == 0x11 && eth->src[2] == 0x25 &&
|
if (type == ARP_ETHERTYPE)
|
||||||
// eth->src[3] == 0xca && eth->src[4] == 0x1f && eth->src[5] == 0x01 && type == 0x800)
|
{
|
||||||
if(type == 0x800)
|
arp_receive(inf, net_link_inf, nb);
|
||||||
return 0;
|
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 ();
|
current_time = grub_get_time_ms ();
|
||||||
if (current_time - start_time > TIMEOUT_TIME_MS)
|
if (current_time - start_time > TIMEOUT_TIME_MS)
|
||||||
|
@ -77,7 +80,7 @@ recv_ethernet_packet (struct grub_net_network_layer_interface *inf __attribute__
|
||||||
- verify if the next layer is the desired one.
|
- verify if the next layer is the desired one.
|
||||||
- if not. get another packet.
|
- if not. get another packet.
|
||||||
- remove ethernet header from buffer*/
|
- 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",
|
.name = "ethernet",
|
||||||
.id = GRUB_NET_ETHERNET_ID,
|
.id = GRUB_NET_ETHERNET_ID,
|
||||||
|
.type = ARPHRD_ETHERNET,
|
||||||
.send = send_ethernet_packet,
|
.send = send_ethernet_packet,
|
||||||
.recv = recv_ethernet_packet
|
.recv = recv_ethernet_packet
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,7 +22,6 @@ INTERFACE_REGISTER_FUNCTIONS("link");*/
|
||||||
|
|
||||||
#include <grub/mm.h>
|
#include <grub/mm.h>
|
||||||
#include <grub/net/interface.h>
|
#include <grub/net/interface.h>
|
||||||
struct grub_net_protocol_stack *grub_net_protocol_stacks;
|
|
||||||
struct grub_net_protocol_stack
|
struct grub_net_protocol_stack
|
||||||
*grub_net_protocol_stack_get (char *name)
|
*grub_net_protocol_stack_get (char *name)
|
||||||
{
|
{
|
||||||
|
|
27
net/ip.c
27
net/ip.c
|
@ -1,6 +1,7 @@
|
||||||
#include <grub/net/ip.h>
|
#include <grub/net/ip.h>
|
||||||
#include <grub/net/ieee1275/interface.h>
|
#include <grub/net/ieee1275/interface.h>
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
#include <grub/net/ethernet.h>
|
#include <grub/net/ethernet.h>
|
||||||
#include <grub/net/interface.h>
|
#include <grub/net/interface.h>
|
||||||
#include <grub/net/type_net.h>
|
#include <grub/net/type_net.h>
|
||||||
|
@ -36,6 +37,8 @@ send_ip_packet (struct grub_net_network_layer_interface *inf,
|
||||||
|
|
||||||
struct iphdr *iph;
|
struct iphdr *iph;
|
||||||
static int id = 0x2400;
|
static int id = 0x2400;
|
||||||
|
struct grub_net_addr nl_target_addr, ll_target_addr;
|
||||||
|
grub_err_t rc;
|
||||||
|
|
||||||
grub_netbuff_push(nb,sizeof(*iph));
|
grub_netbuff_push(nb,sizeof(*iph));
|
||||||
iph = (struct iphdr *) nb->data;
|
iph = (struct iphdr *) nb->data;
|
||||||
|
@ -51,12 +54,26 @@ send_ip_packet (struct grub_net_network_layer_interface *inf,
|
||||||
iph->ttl = 0xff;
|
iph->ttl = 0xff;
|
||||||
iph->protocol = 0x11;
|
iph->protocol = 0x11;
|
||||||
iph->src = (grub_uint32_t) bootp_pckt -> yiaddr; //inf->address.ipv4; // *((grub_uint32_t *)inf->card->ila->addr);
|
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 = 0 ;
|
||||||
iph->chksum = ipchksum((void *)nb->data, sizeof(*iph));
|
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);
|
//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();
|
start_time = grub_get_time_ms();
|
||||||
while (1)
|
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;
|
iph = (struct iphdr *) nb->data;
|
||||||
if (iph->protocol == 0x11 &&
|
if (iph->protocol == 0x11 &&
|
||||||
iph->dest == (grub_uint32_t) bootp_pckt -> yiaddr &&
|
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));
|
grub_netbuff_pull(nb,sizeof(*iph));
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -99,6 +117,7 @@ static struct grub_net_network_layer_protocol grub_ipv4_protocol =
|
||||||
{
|
{
|
||||||
.name = "ipv4",
|
.name = "ipv4",
|
||||||
.id = GRUB_NET_IPV4_ID,
|
.id = GRUB_NET_IPV4_ID,
|
||||||
|
.type = IP_ETHERTYPE,
|
||||||
.send = send_ip_packet,
|
.send = send_ip_packet,
|
||||||
.recv = recv_ip_packet
|
.recv = recv_ip_packet
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,7 +72,7 @@ struct grub_net_buff *grub_netbuff_alloc ( grub_size_t len )
|
||||||
len = NETBUFFMINLEN;
|
len = NETBUFFMINLEN;
|
||||||
|
|
||||||
len = ALIGN_UP (len,NETBUFF_ALIGN);
|
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 = (struct grub_net_buff *) ((int)data + len);
|
||||||
nb->head = nb->data = nb->tail = data;
|
nb->head = nb->data = nb->tail = data;
|
||||||
nb->end = (char *) nb;
|
nb->end = (char *) nb;
|
||||||
|
|
|
@ -113,7 +113,7 @@ tftp_open (struct grub_net_network_layer_interface *inf __attribute((unused)),
|
||||||
app_interface->trans_prot->send (inf,protstack->interface,nb);
|
app_interface->trans_prot->send (inf,protstack->interface,nb);
|
||||||
/*Receive OACK*/
|
/*Receive OACK*/
|
||||||
grub_netbuff_clear (nb);
|
grub_netbuff_clear (nb);
|
||||||
grub_netbuff_reserve (nb,80*1024);
|
grub_netbuff_reserve (nb,2048);
|
||||||
return app_interface->app_prot->recv(inf,protstack,nb);
|
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);
|
tftp_open (inf, protocol_stack,nb, filename);
|
||||||
grub_netbuff_clear (nb);
|
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);
|
tftp_send_err (inf, protocol_stack,nb,"Abort transference.",0);
|
||||||
|
|
||||||
return tftp_file.size;
|
return tftp_file.size;
|
||||||
|
|
|
@ -54,7 +54,7 @@ grub_normal_print_device_info (const char *name)
|
||||||
grub_printf_(N_("Protocol: %s"), "Unknown");
|
grub_printf_(N_("Protocol: %s"), "Unknown");
|
||||||
grub_putchar ('\n');
|
grub_putchar ('\n');
|
||||||
grub_putchar ('\t');
|
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)
|
if (data->username)
|
||||||
{
|
{
|
||||||
grub_putchar ('\n');
|
grub_putchar ('\n');
|
||||||
|
|
Loading…
Reference in a new issue