diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c index 0fc779966..906a688dc 100644 --- a/grub-core/net/drivers/efi/efinet.c +++ b/grub-core/net/drivers/efi/efinet.c @@ -42,43 +42,65 @@ send_card_buffer (const struct grub_net_card *dev, return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, - struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_efi_simple_network_t *net = dev->efi_net; grub_err_t err; grub_efi_status_t st; - grub_efi_uintn_t bufsize = 1500; + grub_efi_uintn_t bufsize = 1536; + struct grub_net_buff *nb; - err = grub_netbuff_clear (nb); - if (err) - return -1; + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; - err = grub_netbuff_put (nb, 1500); - if (err) - return -1; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); if (st == GRUB_EFI_BUFFER_TOO_SMALL) { - err = grub_netbuff_put (nb, bufsize - 1500); - if (err) - return -1; + grub_netbuff_free (nb); + + bufsize = ALIGN_UP (bufsize, 32); + + nb = grub_netbuff_alloc (bufsize); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + st = efi_call_7 (net->receive, net, NULL, &bufsize, nb->data, NULL, NULL, NULL); } if (st != GRUB_EFI_SUCCESS) { - grub_netbuff_clear (nb); - return -1; + grub_netbuff_free (nb); + return NULL; } - err = grub_netbuff_unput (nb, (nb->tail - nb->data) - bufsize); + err = grub_netbuff_put (nb, bufsize); if (err) - return -1; + { + grub_netbuff_free (nb); + return NULL; + } - return bufsize; + return nb; } static struct grub_net_card_driver efidriver = diff --git a/grub-core/net/drivers/emu/emunet.c b/grub-core/net/drivers/emu/emunet.c index 96f773340..ff333d370 100644 --- a/grub-core/net/drivers/emu/emunet.c +++ b/grub-core/net/drivers/emu/emunet.c @@ -43,19 +43,34 @@ send_card_buffer (const struct grub_net_card *dev __attribute__ ((unused)), return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *pack) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev __attribute__ ((unused))) { ssize_t actual; + struct grub_net_buff *nb; - grub_netbuff_clear (pack); - actual = read (fd, pack->data, 1500); + nb = grub_netbuff_alloc (1536); + if (!nb) + return NULL; + + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } + + actual = read (fd, nb->data, 1536); if (actual < 0) - return -1; - grub_netbuff_put (pack, actual); + { + grub_netbuff_free (nb); + return NULL; + } + grub_netbuff_put (nb, actual); - return actual; + return nb; } static struct grub_net_card_driver emudriver = diff --git a/grub-core/net/drivers/i386/pc/pxe.c b/grub-core/net/drivers/i386/pc/pxe.c index 588673177..6c5f2fdc4 100644 --- a/grub-core/net/drivers/i386/pc/pxe.c +++ b/grub-core/net/drivers/i386/pc/pxe.c @@ -164,14 +164,13 @@ grub_pxe_scan (void) return bangpxe; } -static grub_ssize_t -grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), - struct grub_net_buff *buf) +static struct grub_net_buff * +grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused))) { struct grub_pxe_undi_isr *isr; static int in_progress = 0; char *ptr, *end; - int len; + struct grub_net_buff *buf; isr = (void *) GRUB_MEMORY_MACHINE_SCRATCH_ADDR; @@ -183,7 +182,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_OURS) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_PROCESS; @@ -201,17 +200,27 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag == GRUB_PXE_ISR_OUT_DONE) { in_progress = 0; - return -1; + return NULL; } grub_memset (isr, 0, sizeof (*isr)); isr->func_flag = GRUB_PXE_ISR_IN_GET_NEXT; grub_pxe_call (GRUB_PXENV_UNDI_ISR, isr, pxe_rm_entry); } - grub_netbuff_put (buf, isr->frame_len); + buf = grub_netbuff_alloc (isr->frame_len); + if (!buf) + return NULL; + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (buf, 2); + if (!buf) + { + grub_netbuff_free (buf); + return NULL; + } ptr = buf->data; end = ptr + isr->frame_len; - len = isr->frame_len; + grub_netbuff_put (buf, isr->frame_len); grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); ptr += isr->buffer_len; while (ptr < end) @@ -222,7 +231,8 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), if (isr->status || isr->func_flag != GRUB_PXE_ISR_OUT_RECEIVE) { in_progress = 1; - return -1; + grub_netbuff_free (buf); + return NULL; } grub_memcpy (ptr, LINEAR (isr->buffer), isr->buffer_len); @@ -230,7 +240,7 @@ grub_pxe_recv (const struct grub_net_card *dev __attribute__ ((unused)), } in_progress = 1; - return len; + return buf; } static grub_err_t diff --git a/grub-core/net/drivers/ieee1275/ofnet.c b/grub-core/net/drivers/ieee1275/ofnet.c index 035a96220..9c0c84c65 100644 --- a/grub-core/net/drivers/ieee1275/ofnet.c +++ b/grub-core/net/drivers/ieee1275/ofnet.c @@ -73,25 +73,35 @@ send_card_buffer (const struct grub_net_card *dev, struct grub_net_buff *pack) return GRUB_ERR_NONE; } -static grub_ssize_t -get_card_packet (const struct grub_net_card *dev, struct grub_net_buff *nb) +static struct grub_net_buff * +get_card_packet (const struct grub_net_card *dev) { grub_ssize_t actual; int rc; struct grub_ofnetcard_data *data = dev->data; grub_uint64_t start_time; + struct grub_net_buff *nb; - grub_netbuff_clear (nb); + nb = grub_netbuff_alloc (dev->mtu + 64); + /* Reserve 2 bytes so that 2 + 14/18 bytes of ethernet header is divisible + by 4. So that IP header is aligned on 4 bytes. */ + grub_netbuff_reserve (nb, 2); + if (!nb) + { + grub_netbuff_free (nb); + return NULL; + } start_time = grub_get_time_ms (); do - rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu, &actual); + rc = grub_ieee1275_read (data->handle, nb->data, dev->mtu + 64, &actual); while ((actual <= 0 || rc < 0) && (grub_get_time_ms () - start_time < 200)); if (actual) { grub_netbuff_put (nb, actual); - return actual; + return nb; } - return -1; + grub_netbuff_free (nb); + return NULL; } static struct grub_net_card_driver ofdriver = diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c index ee3ccd4d6..eaecc9ea6 100644 --- a/grub-core/net/ip.c +++ b/grub-core/net/ip.c @@ -123,6 +123,9 @@ grub_net_recv_ip_packets (struct grub_net_buff * nb, struct grub_net_network_level_interface *inf = NULL; grub_net_network_level_address_t source; + if (((grub_addr_t) nb->data) & 3) + grub_fatal ("unaligned %p\n", nb->data); + if ((iph->verhdrlen >> 4) != 4) { grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4)); diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 7bed078e3..ab0fbd3c5 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -764,19 +764,10 @@ receive_packets (struct grub_net_card *card) /* Maybe should be better have a fixed number of packets for each card and just mark them as used and not used. */ struct grub_net_buff *nb; - grub_ssize_t actual; - nb = grub_netbuff_alloc (1500); + + nb = card->driver->recv (card); if (!nb) { - grub_print_error (); - card->last_poll = grub_get_time_ms (); - return; - } - - actual = card->driver->recv (card, nb); - if (actual < 0) - { - grub_netbuff_free (nb); card->last_poll = grub_get_time_ms (); break; } diff --git a/include/grub/net.h b/include/grub/net.h index f3c0489e2..83f260d63 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -64,8 +64,7 @@ struct grub_net_card_driver void (*close) (const struct grub_net_card *dev); grub_err_t (*send) (const struct grub_net_card *dev, struct grub_net_buff *buf); - grub_ssize_t (*recv) (const struct grub_net_card *dev, - struct grub_net_buff *buf); + struct grub_net_buff * (*recv) (const struct grub_net_card *dev); }; typedef struct grub_net_packet