Fix a bunch of net issues

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-09-23 00:45:39 +02:00
parent ce3a2ec025
commit 04d22dddd9
9 changed files with 181 additions and 196 deletions

View file

@ -6,7 +6,7 @@
#include <grub/net/ip.h>
#include <grub/time.h>
static struct arp_entry arp_table[SIZE_ARP_TABLE];
static struct arp_entry arp_table[10];
static grub_int8_t new_table_entry = -1;
static
@ -19,8 +19,8 @@ void arp_init_table(void)
static struct arp_entry *
arp_find_entry (const grub_net_network_level_address_t *proto)
{
grub_uint8_t i;
for(i=0;i < SIZE_ARP_TABLE; i++)
unsigned i;
for(i = 0; i < ARRAY_SIZE (arp_table); i++)
{
if(arp_table[i].avail == 1 &&
arp_table[i].nl_address.ipv4 == proto->ipv4)
@ -48,24 +48,26 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
return GRUB_ERR_NONE;
}
/* Build a request packet */
nb = grub_malloc (2048);
nb = grub_netbuff_alloc (2048);
if (!nb)
return grub_errno;
grub_netbuff_reserve(nb, 2048);
grub_netbuff_push(nb, sizeof(*arp_header) + 2 * (6 + 6));
arp_header = (struct arphdr *)nb->data;
arp_header->hrd = 0;
arp_header->pro = 0;
arp_header->hrd = grub_cpu_to_be16 (GRUB_NET_ARPHRD_ETHERNET);
arp_header->pro = grub_cpu_to_be16 (GRUB_NET_ETHERTYPE_IP);
arp_header->hln = 6;
arp_header->pln = 6;
arp_header->op = ARP_REQUEST;
arp_header->pln = 4;
arp_header->op = grub_cpu_to_be16 (ARP_REQUEST);
aux = (grub_uint8_t *)arp_header + sizeof(*arp_header);
/* Sender hardware address */
grub_memcpy(aux, &inf->hwaddress.mac, 6);
aux += 6;
/* Sender protocol address */
grub_memcpy(aux, &inf->address.ipv4, 4);
aux += 6;
aux += 4;
/* Target hardware address */
for(i=0; i < 6; i++)
for(i = 0; i < 6; i++)
aux[i] = 0x00;
aux += 6;
/* Target protocol address */
@ -73,7 +75,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
grub_memset (&target_hw_addr.mac, 0xff, 6);
send_ethernet_packet (inf, nb, target_hw_addr, ARP_ETHERTYPE);
send_ethernet_packet (inf, nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
grub_netbuff_clear(nb);
grub_netbuff_reserve(nb, 2048);
@ -81,7 +83,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
start_time = grub_get_time_ms();
do
{
grub_net_recv_ethernet_packet (inf, nb, ARP_ETHERTYPE);
grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_ARP);
/* Now check cache table again */
entry = arp_find_entry(proto_addr);
if (entry)
@ -90,7 +92,7 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
grub_netbuff_clear(nb);
return GRUB_ERR_NONE;
}
current_time = grub_get_time_ms();
current_time = grub_get_time_ms();
if (current_time - start_time > 3000)
break;
} while (! entry);
@ -99,17 +101,16 @@ grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
}
grub_err_t
grub_net_arp_receive(struct grub_net_network_level_interface *inf,
struct grub_net_buff *nb)
grub_net_arp_receive (struct grub_net_network_level_interface *inf,
struct grub_net_buff *nb)
{
struct arphdr *arp_header = (struct arphdr *)nb->data;
struct arp_entry *entry;
grub_uint8_t merge = 0;
grub_uint8_t *sender_hardware_address, *sender_protocol_address;
grub_uint8_t *target_hardware_address, *target_protocol_address;
grub_net_network_level_address_t hwaddress;
sender_hardware_address = (grub_uint8_t *)arp_header + sizeof(*arp_header);
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;
@ -118,40 +119,36 @@ grub_net_arp_receive(struct grub_net_network_level_interface *inf,
entry = arp_find_entry(&hwaddress);
/* Update sender hardware address */
if (entry)
grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6);
else
{
grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6);
merge = 1;
}
/* Am I the protocol address target? */
if (! grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6))
{
/* Add sender to cache table */
if (! merge)
{
/* Add sender to cache table */
if (new_table_entry == -1)
arp_init_table();
arp_init_table();
entry = &(arp_table[new_table_entry]);
entry->avail = 1;
grub_memcpy(&entry->nl_address.ipv4, sender_protocol_address, 4);
grub_memcpy(entry->ll_address.mac, sender_hardware_address, 6);
new_table_entry++;
if (new_table_entry == SIZE_ARP_TABLE)
new_table_entry = 0;
}
if (arp_header->op == ARP_REQUEST)
{
grub_net_link_level_address_t aux;
/* Swap hardware fields */
grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln);
grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6);
grub_memcpy(aux.mac, sender_protocol_address, 6);
grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln);
grub_memcpy(target_protocol_address, aux.mac, arp_header->pln);
/* Change operation to REPLY and send packet */
arp_header->op = ARP_REPLY;
grub_memcpy (aux.mac, target_hardware_address, 6);
send_ethernet_packet (inf, nb, aux, ARP_ETHERTYPE);
}
if (new_table_entry == ARRAY_SIZE (arp_table))
new_table_entry = 0;
}
/* Am I the protocol address target? */
if (grub_memcmp(target_protocol_address, inf->hwaddress.mac, 6) == 0
&& grub_be_to_cpu16 (arp_header->op) == ARP_REQUEST)
{
grub_net_link_level_address_t aux;
/* Swap hardware fields */
grub_memcpy(target_hardware_address, sender_hardware_address, arp_header->hln);
grub_memcpy(sender_hardware_address, inf->hwaddress.mac, 6);
grub_memcpy(aux.mac, sender_protocol_address, 6);
grub_memcpy(sender_protocol_address, target_protocol_address, arp_header->pln);
grub_memcpy(target_protocol_address, aux.mac, arp_header->pln);
/* Change operation to REPLY and send packet */
arp_header->op = grub_be_to_cpu16 (ARP_REPLY);
grub_memcpy (aux.mac, target_hardware_address, 6);
send_ethernet_packet (inf, nb, aux, GRUB_NET_ETHERTYPE_ARP);
}
return GRUB_ERR_NONE;
}

View file

@ -1,68 +1,92 @@
#include <grub/dl.h>
#include <grub/net/netbuff.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h> /* the L2 protocols */
#include <grub/net.h>
#include <sys/types.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
#include <grub/term.h>
static int fd;
static grub_err_t
card_open (struct grub_net_card *dev)
{
dev->data_num = socket (AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (dev->data_num < 0)
return grub_error (GRUB_ERR_IO, "couldn't open packet interface");
return GRUB_ERR_NONE;
}
static grub_err_t
card_close (struct grub_net_card *dev)
{
close (dev->data_num);
return GRUB_ERR_NONE;
}
static grub_err_t
send_card_buffer (struct grub_net_card *dev, struct grub_net_buff *pack)
send_card_buffer (struct grub_net_card *dev __attribute__ ((unused)),
struct grub_net_buff *pack)
{
ssize_t actual;
actual = write (dev->data_num, pack->data, pack->tail - pack->data);
actual = write (fd, pack->data, pack->tail - pack->data);
if (actual < 0)
return grub_error (GRUB_ERR_IO, "couldn't send packets");
return GRUB_ERR_NONE;
}
static grub_err_t
get_card_packet (struct grub_net_card *dev, struct grub_net_buff *pack)
static grub_size_t
get_card_packet (struct grub_net_card *dev __attribute__ ((unused)),
struct grub_net_buff *pack)
{
ssize_t actual;
grub_netbuff_clear(pack);
actual = read (dev->data_num, pack->data, 1500);
actual = read (fd, pack->data, 1500);
if (actual < 0)
return grub_error (GRUB_ERR_IO, "couldn't receive packets");
{
grub_error (GRUB_ERR_IO, "couldn't receive packets");
return -1;
}
grub_netbuff_put (pack, actual);
return GRUB_ERR_NONE;
return actual;
}
static struct grub_net_card_driver emudriver =
{
.name = "emu",
.init = card_open,
.fini = card_close,
.send = send_card_buffer,
.recv = get_card_packet
};
static struct grub_net_card emucard =
{
.name = "emu0",
.driver = &emudriver,
.default_address = {
.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET,
{ .mac = { 0, 1, 2, 3, 4, 5} }
},
.flags = 0
};
GRUB_MOD_INIT(emunet)
{
grub_net_card_driver_register (&emudriver);
struct ifreq ifr;
// char fullname[64];
fd = open ("/dev/net/tun", O_RDWR | O_NONBLOCK);
if (fd < 0)
return;
grub_memset (&ifr, 0, sizeof (ifr));
ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
if (ioctl (fd, TUNSETIFF, &ifr) < 0)
{
close (fd);
fd = -1;
return;
}
grub_net_card_register (&emucard);
}
GRUB_MODE_FINI(emunet)
GRUB_MOD_FINI(emunet)
{
grub_net_card_driver_unregister (&emudriver);
if (fd >= 0)
{
close (fd);
grub_net_card_unregister (&emucard);
}
}

View file

@ -38,10 +38,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf,
inf->card->driver->recv (inf->card, nb);
eth = (struct etherhdr *) nb->data;
type = eth->type;
type = grub_be_to_cpu16 (eth->type);
grub_netbuff_pull(nb,sizeof (*eth));
if (eth->type <=1500)
if (type <= 1500)
{
llch = (struct llchdr *) nb->data;
type = llch->dsap & LLCADDRMASK;
@ -55,14 +55,10 @@ grub_net_recv_ethernet_packet (struct grub_net_network_level_interface *inf,
}
/* ARP packet */
if (type == ARP_ETHERTYPE)
{
grub_net_arp_receive(inf, nb);
if (ethertype == ARP_ETHERTYPE)
return GRUB_ERR_NONE;
}
if (type == GRUB_NET_ETHERTYPE_ARP)
grub_net_arp_receive(inf, nb);
/* IP packet */
else if(type == IP_ETHERTYPE && ethertype == IP_ETHERTYPE)
if(type == GRUB_NET_ETHERTYPE_IP && ethertype == GRUB_NET_ETHERTYPE_IP)
return GRUB_ERR_NONE;
return GRUB_ERR_NONE;

View file

@ -54,7 +54,7 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
if (err)
return err;
return send_ethernet_packet (inf, nb, ll_target_addr, IP_ETHERTYPE);
return send_ethernet_packet (inf, nb, ll_target_addr, GRUB_NET_ETHERTYPE_IP);
}
static int
@ -84,8 +84,11 @@ ip_filter (struct grub_net_buff *nb,
grub_err_t
grub_net_recv_ip_packets (struct grub_net_network_level_interface *inf)
{
struct grub_net_buff nb;
grub_net_recv_ethernet_packet (inf, &nb, IP_ETHERTYPE);
ip_filter (&nb, inf);
struct grub_net_buff *nb;
nb = grub_netbuff_alloc (2048);
if (!nb)
return grub_errno;
grub_net_recv_ethernet_packet (inf, nb, GRUB_NET_ETHERTYPE_IP);
ip_filter (nb, inf);
return GRUB_ERR_NONE;
}

View file

@ -92,7 +92,7 @@ parse_ip (const char *val, grub_uint32_t *ip, const char **rest)
*ip = grub_cpu_to_le32 (newip);
if (rest)
*rest = ptr - 1;
return 0;
return 1;
}
static int
@ -341,7 +341,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)),
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("three arguments expected"));
FOR_NET_CARDS (card)
if (grub_strcmp (card->name, args[1]))
if (grub_strcmp (card->name, args[1]) == 0)
break;
if (card == NULL)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("card not found"));
@ -464,7 +464,7 @@ grub_cmd_addroute (struct grub_command *cmd __attribute__ ((unused)),
struct grub_net_network_level_interface *inter;
FOR_NET_NETWORK_LEVEL_INTERFACES (inter)
if (grub_strcmp (inter->name, args[2]))
if (grub_strcmp (inter->name, args[2]) == 0)
break;
if (!inter)

View file

@ -9,60 +9,15 @@
#include <grub/dl.h>
#include <grub/file.h>
struct {
int block_size;
int size;
} tftp_file;
static int block;
static char *get_tok_val(char **tok, char **val, char **str_opt,char *end);
static void process_option(char *tok, char *val);
static char *
get_tok_val(char **tok, char **val,char **str_opt,char *end)
{
char *p = *str_opt;
*tok = p;
p += grub_strlen(p) + 1;
if(p > end)
return NULL;
*val = p;
p += grub_strlen(p) + 1;
*str_opt = p;
return *tok;
}
static void
process_option(char *tok, char *val)
{
if (!grub_strcmp(tok,"blksize"))
{
tftp_file.block_size = grub_strtoul (val,NULL,0);
return;
}
if (!grub_strcmp(tok,"tsize"))
{
tftp_file.size = grub_strtoul (val,NULL,0);
return;
}
}
//void tftp_open (char *options);
/*send read request*/
static grub_err_t
tftp_open (struct grub_file *file, const char *filename)
{
struct tftphdr *tftph;
char *rrq;
char *ptr;
int rrqlen;
int hdrlen;
struct grub_net_buff nb;
struct grub_net_buff *nb;
grub_net_network_level_address_t addr;
grub_err_t err;
@ -70,29 +25,28 @@ tftp_open (struct grub_file *file, const char *filename)
+ sizeof ("tftp,") - 1, &addr);
if (err)
return err;
grub_memset (&nb, 0, sizeof (nb));
grub_netbuff_push (&nb,sizeof (*tftph));
tftph = (struct tftphdr *) nb.data;
nb = grub_netbuff_alloc (2048);
if (!nb)
return grub_errno;
grub_netbuff_reserve (nb,2048);
grub_netbuff_push (nb,sizeof (*tftph));
tftph = (struct tftphdr *) nb->data;
rrq = (char *) tftph->u.rrq;
rrqlen = 0;
tftph->opcode = TFTP_RRQ;
tftph->opcode = grub_cpu_to_be16 (TFTP_RRQ);
grub_strcpy (rrq, filename);
rrqlen += grub_strlen (filename) + 1;
rrq += grub_strlen (filename) + 1;
/*passar opcoes como parametro ou usar default?*/
grub_strcpy (rrq,"octet");
rrqlen += grub_strlen ("octet") + 1;
rrq += grub_strlen ("octet") + 1;
//grub_strcpy (rrq,"netascii");
//rrqlen += grub_strlen ("netascii") + 1;
//rrq += grub_strlen ("netascii") + 1;
grub_strcpy (rrq,"blksize");
rrqlen += grub_strlen("blksize") + 1;
rrq += grub_strlen ("blksize") + 1;
@ -107,29 +61,53 @@ tftp_open (struct grub_file *file, const char *filename)
grub_strcpy (rrq,"0");
rrqlen += grub_strlen ("0") + 1;
rrq += grub_strlen ("0") + 1;
rrq += grub_strlen ("0") + 1;
hdrlen = sizeof (tftph->opcode) + rrqlen;
grub_netbuff_unput (&nb,nb.tail - (nb.data+hdrlen));
grub_netbuff_unput (nb,nb->tail - (nb->data+hdrlen));
grub_net_send_udp_packet (&addr,
&nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
err = grub_net_send_udp_packet (&addr,
nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
if (err)
return err;
grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
/*Receive OACK*/
grub_netbuff_clear (&nb);
grub_netbuff_reserve (&nb,2048);
file->size = tftp_file.size;
/* Receive OACK. */
grub_netbuff_clear (nb);
grub_netbuff_reserve (nb,2048);
return grub_net_recv_udp_packet (&addr, &nb,
TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
do
{
err = grub_net_recv_udp_packet (&addr, nb,
TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
if (err)
return err;
}
while (nb->tail == nb->data);
file->size = 0;
for (ptr = nb->data; ptr < nb->tail; )
grub_printf ("%02x ", *ptr);
for (ptr = nb->data; ptr < nb->tail; )
{
if (grub_memcmp (ptr, "tsize\0=", sizeof ("tsize\0=") - 1) == 0)
{
file->size = grub_strtoul (ptr + sizeof ("tsize\0=") - 1, 0, 0);
grub_errno = GRUB_ERR_NONE;
}
while (ptr < nb->tail && *ptr)
ptr++;
ptr++;
}
return GRUB_ERR_NONE;
}
static grub_ssize_t
tftp_receive (struct grub_file *file, char *buf, grub_size_t len)
{
struct tftphdr *tftph;
char *token,*value,*temp;
// char *token,*value,*temp;
grub_err_t err;
grub_net_network_level_address_t addr;
struct grub_net_buff nb;
@ -143,38 +121,21 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len)
TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
tftph = (struct tftphdr *) nb.data;
switch (tftph->opcode)
switch (grub_be_to_cpu16 (tftph->opcode))
{
case TFTP_OACK:
/*process oack packet*/
temp = (char *) tftph->u.oack.data;
while(get_tok_val(&token,&value,&temp,nb.tail))
{
process_option(token,value);
}
//buff_clean
grub_netbuff_clear(&nb);
// grub_printf("OACK---------------------------------------------------------\n");
//grub_printf("block_size=%d\n",tftp_file.block_size);
// grub_printf("file_size=%d\n",tftp_file.size);
// grub_printf("OACK---------------------------------------------------------\n");
block = 0;
break;
case TFTP_DATA:
grub_netbuff_pull (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.data.block));
if (tftph->u.data.block == block + 1)
{
block = tftph->u.data.block;
// if (tftph->u.data.block == block + 1)
//{
// block = tftph->u.data.block;
grub_memcpy (buf, nb.data, len);
}
else
grub_netbuff_clear(&nb);
break;
//}
//else
//grub_netbuff_clear(&nb);
break;
case TFTP_ERROR:
grub_netbuff_clear (&nb);
return grub_error (GRUB_ERR_ACCESS_DENIED, (char *)tftph->u.err.errmsg);
break;
return grub_error (GRUB_ERR_IO, (char *)tftph->u.err.errmsg);
}
nb.data = nb.tail = nb.end;
@ -182,8 +143,8 @@ tftp_receive (struct grub_file *file, char *buf, grub_size_t len)
grub_netbuff_push (&nb,sizeof (tftph->opcode) + sizeof (tftph->u.ack.block));
tftph = (struct tftphdr *) nb.data;
tftph->opcode = TFTP_ACK;
tftph->u.ack.block = block;
tftph->opcode = grub_cpu_to_be16 (TFTP_ACK);
// tftph->u.ack.block = block;
return grub_net_send_udp_packet (&addr, &nb, TFTP_CLIENT_PORT, TFTP_SERVER_PORT);
}

View file

@ -3,13 +3,11 @@
#include <grub/misc.h>
#include <grub/net.h>
/* 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
enum
{
/* IANA ARP constant to define hardware type as ethernet. */
GRUB_NET_ARPHRD_ETHERNET = 1
};
/* ARP header operation codes */
#define ARP_REQUEST 1

View file

@ -38,6 +38,14 @@ struct snaphdr
grub_uint16_t type;
} __attribute__ ((packed));
/* IANA Ethertype */
enum
{
GRUB_NET_ETHERTYPE_IP = 0x0800,
GRUB_NET_ETHERTYPE_ARP = 0x0806
};
grub_err_t
send_ethernet_packet (struct grub_net_network_level_interface *inf,
struct grub_net_buff *nb,

View file

@ -2,8 +2,6 @@
#define GRUB_NET_IP_HEADER 1
#include <grub/misc.h>
#define IP_ETHERTYPE 0x800 /* IANA Ethertype */
struct iphdr {
grub_uint8_t verhdrlen;
grub_uint8_t service;