#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];
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);
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);
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)
{
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;
}
{
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)
{
"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 =
{
}
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);
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);
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
{