several net bugfixes and improvements and fix some memory leaks
This commit is contained in:
parent
da1b289afc
commit
bd40efbf0b
8 changed files with 365 additions and 180 deletions
|
@ -35,6 +35,7 @@ struct grub_bufio
|
||||||
grub_file_t file;
|
grub_file_t file;
|
||||||
grub_size_t block_size;
|
grub_size_t block_size;
|
||||||
grub_size_t buffer_len;
|
grub_size_t buffer_len;
|
||||||
|
grub_off_t buffer_at;
|
||||||
char buffer[0];
|
char buffer[0];
|
||||||
};
|
};
|
||||||
typedef struct grub_bufio *grub_bufio_t;
|
typedef struct grub_bufio *grub_bufio_t;
|
||||||
|
@ -70,6 +71,7 @@ grub_bufio_open (grub_file_t io, int size)
|
||||||
bufio->file = io;
|
bufio->file = io;
|
||||||
bufio->block_size = size;
|
bufio->block_size = size;
|
||||||
bufio->buffer_len = 0;
|
bufio->buffer_len = 0;
|
||||||
|
bufio->buffer_at = 0;
|
||||||
|
|
||||||
file->device = io->device;
|
file->device = io->device;
|
||||||
file->offset = 0;
|
file->offset = 0;
|
||||||
|
@ -104,83 +106,87 @@ grub_buffile_open (const char *name, int size)
|
||||||
static grub_ssize_t
|
static grub_ssize_t
|
||||||
grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
|
grub_bufio_read (grub_file_t file, char *buf, grub_size_t len)
|
||||||
{
|
{
|
||||||
grub_size_t res = len;
|
grub_size_t res = 0;
|
||||||
grub_bufio_t bufio = file->data;
|
grub_bufio_t bufio = file->data;
|
||||||
grub_uint64_t pos;
|
|
||||||
|
|
||||||
if ((file->offset >= bufio->file->offset) &&
|
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||||
(file->offset < bufio->file->offset + bufio->buffer_len))
|
file->size = bufio->file->size;
|
||||||
|
|
||||||
|
/* First part: use whatever we already have in the buffer. */
|
||||||
|
if ((file->offset >= bufio->buffer_at) &&
|
||||||
|
(file->offset < bufio->buffer_at + bufio->buffer_len))
|
||||||
{
|
{
|
||||||
grub_size_t n;
|
grub_size_t n;
|
||||||
|
grub_uint64_t pos;
|
||||||
|
|
||||||
pos = file->offset - bufio->file->offset;
|
pos = file->offset - bufio->buffer_at;
|
||||||
n = bufio->buffer_len - pos;
|
n = bufio->buffer_len - pos;
|
||||||
if (n > len)
|
if (n > len)
|
||||||
n = len;
|
n = len;
|
||||||
|
|
||||||
grub_memcpy (buf, &bufio->buffer[pos], n);
|
grub_memcpy (buf, &bufio->buffer[pos], n);
|
||||||
len -= n;
|
len -= n;
|
||||||
if (! len)
|
res += n;
|
||||||
return res;
|
|
||||||
|
|
||||||
buf += n;
|
buf += n;
|
||||||
bufio->file->offset += bufio->buffer_len;
|
}
|
||||||
pos = 0;
|
if (! len)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
/* Need to read some more. */
|
||||||
|
bufio->buffer_at = grub_divmod64 (file->offset + res + len, bufio->block_size,
|
||||||
|
0) * bufio->block_size;
|
||||||
|
|
||||||
|
/* Now read between file->offset + res and bufio->buffer_at. */
|
||||||
|
if (file->offset + res < bufio->buffer_at)
|
||||||
|
{
|
||||||
|
grub_size_t read_now;
|
||||||
|
grub_ssize_t really_read;
|
||||||
|
read_now = bufio->buffer_at - (file->offset + res);
|
||||||
|
grub_file_seek (bufio->file, file->offset + res);
|
||||||
|
really_read = grub_file_read (bufio->file, buf, read_now);
|
||||||
|
if (grub_errno)
|
||||||
|
return -1;
|
||||||
|
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||||
|
file->size = bufio->file->size;
|
||||||
|
len -= really_read;
|
||||||
|
buf += really_read;
|
||||||
|
res += really_read;
|
||||||
|
|
||||||
|
/* Partial read. File ended unexpectedly. Save the last chunk in buffer.
|
||||||
|
*/
|
||||||
|
if (really_read != (grub_ssize_t) read_now)
|
||||||
|
{
|
||||||
|
bufio->buffer_len = really_read;
|
||||||
|
if (bufio->buffer_len > bufio->block_size)
|
||||||
|
bufio->buffer_len = bufio->block_size;
|
||||||
|
bufio->buffer_at = file->offset + res - bufio->buffer_len;
|
||||||
|
grub_memcpy (&bufio->buffer[0], buf - bufio->buffer_len,
|
||||||
|
bufio->buffer_len);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read into buffer. */
|
||||||
|
grub_file_seek (bufio->file, bufio->buffer_at);
|
||||||
|
bufio->buffer_len = grub_file_read (bufio->file, bufio->buffer,
|
||||||
|
bufio->block_size);
|
||||||
|
if (grub_errno)
|
||||||
|
return -1;
|
||||||
|
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||||
|
file->size = bufio->file->size;
|
||||||
|
|
||||||
|
if (len < bufio->buffer_len)
|
||||||
|
{
|
||||||
|
grub_memcpy (buf, &bufio->buffer[0], len);
|
||||||
|
res += len;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size,
|
grub_memcpy (buf, &bufio->buffer[0], bufio->buffer_len);
|
||||||
&pos);
|
res += bufio->buffer_len;
|
||||||
bufio->file->offset *= bufio->block_size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pos + len >= bufio->block_size)
|
|
||||||
{
|
|
||||||
if (pos)
|
|
||||||
{
|
|
||||||
grub_size_t n;
|
|
||||||
|
|
||||||
bufio->file->fs->read (bufio->file, bufio->buffer,
|
|
||||||
bufio->block_size);
|
|
||||||
if (grub_errno)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
n = bufio->block_size - pos;
|
|
||||||
grub_memcpy (buf, &bufio->buffer[pos], n);
|
|
||||||
len -= n;
|
|
||||||
buf += n;
|
|
||||||
bufio->file->offset += bufio->block_size;
|
|
||||||
pos = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (len >= bufio->block_size)
|
|
||||||
{
|
|
||||||
bufio->file->fs->read (bufio->file, buf, bufio->block_size);
|
|
||||||
if (grub_errno)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
len -= bufio->block_size;
|
|
||||||
buf += bufio->block_size;
|
|
||||||
bufio->file->offset += bufio->block_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! len)
|
|
||||||
{
|
|
||||||
bufio->buffer_len = 0;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bufio->buffer_len = bufio->file->size - bufio->file->offset;
|
|
||||||
if (bufio->buffer_len > bufio->block_size)
|
|
||||||
bufio->buffer_len = bufio->block_size;
|
|
||||||
|
|
||||||
bufio->file->fs->read (bufio->file, bufio->buffer, bufio->buffer_len);
|
|
||||||
if (grub_errno)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
grub_memcpy (buf, &bufio->buffer[pos], len);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -442,6 +442,7 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_free (tmp_buf);
|
||||||
grub_errno = GRUB_ERR_NONE;
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -468,9 +469,11 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
|
||||||
grub_error_push ();
|
grub_error_push ();
|
||||||
grub_dprintf ("disk", "%s read failed\n", disk->name);
|
grub_dprintf ("disk", "%s read failed\n", disk->name);
|
||||||
grub_error_pop ();
|
grub_error_pop ();
|
||||||
|
grub_free (tmp_buf);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
grub_memcpy (buf, tmp_buf + offset, size);
|
grub_memcpy (buf, tmp_buf + offset, size);
|
||||||
|
grub_free (tmp_buf);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,22 @@ parse_dhcp_vendor (const char *name, void *vend, int limit)
|
||||||
|
|
||||||
switch (tagtype)
|
switch (tagtype)
|
||||||
{
|
{
|
||||||
|
case 3:
|
||||||
|
if (taglength == 4)
|
||||||
|
{
|
||||||
|
grub_net_network_level_netaddress_t target;
|
||||||
|
grub_net_network_level_address_t gw;
|
||||||
|
char rname[grub_strlen (name) + sizeof (":default")];
|
||||||
|
|
||||||
|
target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
|
target.ipv4.base = 0;
|
||||||
|
target.ipv4.masksize = 0;
|
||||||
|
gw.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
|
grub_memcpy (&gw.ipv4, ptr, sizeof (gw.ipv4));
|
||||||
|
grub_snprintf (rname, sizeof (rname), "%s:default", name);
|
||||||
|
grub_net_add_route_gw (rname, target, gw);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 12:
|
case 12:
|
||||||
set_env_limn_ro (name, "hostname", (char *) ptr, taglength);
|
set_env_limn_ro (name, "hostname", (char *) ptr, taglength);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,8 +36,6 @@ enum
|
||||||
|
|
||||||
typedef struct http_data
|
typedef struct http_data
|
||||||
{
|
{
|
||||||
grub_uint64_t file_size;
|
|
||||||
grub_uint64_t position;
|
|
||||||
char *current_line;
|
char *current_line;
|
||||||
grub_size_t current_line_len;
|
grub_size_t current_line_len;
|
||||||
int headers_recv;
|
int headers_recv;
|
||||||
|
@ -47,18 +45,53 @@ typedef struct http_data
|
||||||
char *filename;
|
char *filename;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
char *errmsg;
|
char *errmsg;
|
||||||
|
int chunked;
|
||||||
|
grub_size_t chunk_rem;
|
||||||
|
int in_chunk_len;
|
||||||
} *http_data_t;
|
} *http_data_t;
|
||||||
|
|
||||||
|
static grub_off_t
|
||||||
|
have_ahead (struct grub_file *file)
|
||||||
|
{
|
||||||
|
grub_net_t net = file->device->net;
|
||||||
|
grub_off_t ret = net->offset;
|
||||||
|
struct grub_net_packet *pack;
|
||||||
|
for (pack = net->packs.first; pack; pack = pack->next)
|
||||||
|
ret += pack->nb->tail - pack->nb->data;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
parse_line (http_data_t data, char *ptr, grub_size_t len)
|
parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
|
||||||
{
|
{
|
||||||
char *end = ptr + len;
|
char *end = ptr + len;
|
||||||
while (end > ptr && *(end - 1) == '\r')
|
while (end > ptr && *(end - 1) == '\r')
|
||||||
end--;
|
end--;
|
||||||
*end = 0;
|
*end = 0;
|
||||||
|
/* Trailing CRLF. */
|
||||||
|
if (data->in_chunk_len == 1)
|
||||||
|
{
|
||||||
|
data->in_chunk_len = 2;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (data->in_chunk_len == 2)
|
||||||
|
{
|
||||||
|
data->chunk_rem = grub_strtoul (ptr, 0, 16);
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
if (data->chunk_rem == 0)
|
||||||
|
{
|
||||||
|
file->device->net->eof = 1;
|
||||||
|
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||||
|
file->size = have_ahead (file);
|
||||||
|
}
|
||||||
|
data->in_chunk_len = 0;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
if (ptr == end)
|
if (ptr == end)
|
||||||
{
|
{
|
||||||
data->headers_recv = 1;
|
data->headers_recv = 1;
|
||||||
|
if (data->chunked)
|
||||||
|
data->in_chunk_len = 2;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,10 +126,17 @@ parse_line (http_data_t data, char *ptr, grub_size_t len)
|
||||||
== 0 && !data->size_recv)
|
== 0 && !data->size_recv)
|
||||||
{
|
{
|
||||||
ptr += sizeof ("Content-Length: ") - 1;
|
ptr += sizeof ("Content-Length: ") - 1;
|
||||||
data->file_size = grub_strtoull (ptr, &ptr, 10);
|
file->size = grub_strtoull (ptr, &ptr, 10);
|
||||||
data->size_recv = 1;
|
data->size_recv = 1;
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
if (grub_memcmp (ptr, "Transfer-Encoding: chunked",
|
||||||
|
sizeof ("Transfer-Encoding: chunked") - 1) == 0)
|
||||||
|
{
|
||||||
|
data->chunked = 1;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,6 +153,8 @@ http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
grub_free (data->current_line);
|
grub_free (data->current_line);
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
file->device->net->eof = 1;
|
file->device->net->eof = 1;
|
||||||
|
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||||
|
file->size = have_ahead (file);
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -122,94 +164,116 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||||
{
|
{
|
||||||
grub_file_t file = f;
|
grub_file_t file = f;
|
||||||
http_data_t data = file->data;
|
http_data_t data = file->data;
|
||||||
char *ptr = (char *) nb->data;
|
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
if (!data->headers_recv && data->current_line)
|
while (1)
|
||||||
{
|
{
|
||||||
int have_line = 1;
|
char *ptr = (char *) nb->data;
|
||||||
char *t;
|
if ((!data->headers_recv || data->in_chunk_len) && data->current_line)
|
||||||
ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
|
|
||||||
if (ptr)
|
|
||||||
ptr++;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
have_line = 0;
|
int have_line = 1;
|
||||||
ptr = (char *) nb->tail;
|
char *t;
|
||||||
}
|
ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
|
||||||
t = grub_realloc (data->current_line,
|
if (ptr)
|
||||||
data->current_line_len + (ptr - (char *) nb->data));
|
ptr++;
|
||||||
if (!t)
|
else
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
have_line = 0;
|
||||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
ptr = (char *) nb->tail;
|
||||||
return grub_errno;
|
}
|
||||||
}
|
t = grub_realloc (data->current_line,
|
||||||
|
data->current_line_len + (ptr - (char *) nb->data));
|
||||||
data->current_line = t;
|
if (!t)
|
||||||
grub_memcpy (data->current_line + data->current_line_len,
|
|
||||||
nb->data, ptr - (char *) nb->data);
|
|
||||||
data->current_line_len += ptr - (char *) nb->data;
|
|
||||||
if (!have_line)
|
|
||||||
{
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
err = parse_line (data, data->current_line, data->current_line_len);
|
|
||||||
grub_free (data->current_line);
|
|
||||||
data->current_line = 0;
|
|
||||||
data->current_line_len = 0;
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ptr < (char *) nb->tail && !data->headers_recv)
|
|
||||||
{
|
|
||||||
char *ptr2;
|
|
||||||
ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr);
|
|
||||||
if (!ptr2)
|
|
||||||
{
|
|
||||||
data->current_line = grub_malloc ((char *) nb->tail - ptr);
|
|
||||||
if (!data->current_line)
|
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
data->current_line_len = (char *) nb->tail - ptr;
|
|
||||||
grub_memcpy (data->current_line, ptr, data->current_line_len);
|
data->current_line = t;
|
||||||
|
grub_memcpy (data->current_line + data->current_line_len,
|
||||||
|
nb->data, ptr - (char *) nb->data);
|
||||||
|
data->current_line_len += ptr - (char *) nb->data;
|
||||||
|
if (!have_line)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
err = parse_line (file, data, data->current_line,
|
||||||
|
data->current_line_len);
|
||||||
|
grub_free (data->current_line);
|
||||||
|
data->current_line = 0;
|
||||||
|
data->current_line_len = 0;
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (ptr < (char *) nb->tail && (!data->headers_recv
|
||||||
|
|| data->in_chunk_len))
|
||||||
|
{
|
||||||
|
char *ptr2;
|
||||||
|
ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr);
|
||||||
|
if (!ptr2)
|
||||||
|
{
|
||||||
|
data->current_line = grub_malloc ((char *) nb->tail - ptr);
|
||||||
|
if (!data->current_line)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
data->current_line_len = (char *) nb->tail - ptr;
|
||||||
|
grub_memcpy (data->current_line, ptr, data->current_line_len);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
err = parse_line (file, data, ptr, ptr2 - ptr);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
ptr = ptr2 + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((char *) nb->tail - ptr) <= 0)
|
||||||
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
err = parse_line (data, ptr, ptr2 - ptr);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
ptr = ptr2 + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((char *) nb->tail - ptr) > 0)
|
|
||||||
{
|
|
||||||
data->position += ((char *) nb->tail - ptr);
|
|
||||||
err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
|
err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
grub_net_put_packet (&file->device->net->packs, nb);
|
if (!(data->chunked && (grub_ssize_t) data->chunk_rem
|
||||||
|
< nb->tail - nb->data))
|
||||||
|
{
|
||||||
|
grub_net_put_packet (&file->device->net->packs, nb);
|
||||||
|
if (data->chunked)
|
||||||
|
data->chunk_rem -= nb->tail - nb->data;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (data->chunk_rem)
|
||||||
|
{
|
||||||
|
struct grub_net_buff *nb2;
|
||||||
|
nb2 = grub_netbuff_alloc (data->chunk_rem);
|
||||||
|
if (!nb2)
|
||||||
|
return grub_errno;
|
||||||
|
grub_netbuff_put (nb2, data->chunk_rem);
|
||||||
|
grub_memcpy (nb2->data, nb->data, data->chunk_rem);
|
||||||
|
grub_net_put_packet (&file->device->net->packs, nb2);
|
||||||
|
grub_netbuff_pull (nb, data->chunk_rem);
|
||||||
|
}
|
||||||
|
data->in_chunk_len = 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
|
@ -294,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||||
"\r\n"),
|
"\r\n"),
|
||||||
"Content-Range: bytes %" PRIuGRUB_UINT64_T "-%"
|
"Content-Range: bytes %" PRIuGRUB_UINT64_T "-%"
|
||||||
PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n",
|
PRIuGRUB_UINT64_T "/%" PRIuGRUB_UINT64_T "\r\n\r\n",
|
||||||
offset, data->file_size - 1, data->file_size);
|
offset, file->size - 1, file->size);
|
||||||
grub_netbuff_put (nb, grub_strlen ((char *) ptr));
|
grub_netbuff_put (nb, grub_strlen ((char *) ptr));
|
||||||
}
|
}
|
||||||
ptr = nb->tail;
|
ptr = nb->tail;
|
||||||
|
@ -303,7 +367,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||||
|
|
||||||
data->sock = grub_net_tcp_open (file->device->net->server,
|
data->sock = grub_net_tcp_open (file->device->net->server,
|
||||||
HTTP_PORT, http_receive,
|
HTTP_PORT, http_receive,
|
||||||
http_err,
|
http_err, http_err,
|
||||||
file);
|
file);
|
||||||
if (!data->sock)
|
if (!data->sock)
|
||||||
{
|
{
|
||||||
|
@ -351,13 +415,17 @@ http_seek (struct grub_file *file, grub_off_t off)
|
||||||
grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT);
|
grub_net_tcp_close (old_data->sock, GRUB_NET_TCP_ABORT);
|
||||||
|
|
||||||
while (file->device->net->packs.first)
|
while (file->device->net->packs.first)
|
||||||
grub_net_remove_packet (file->device->net->packs.first);
|
{
|
||||||
|
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||||
|
grub_net_remove_packet (file->device->net->packs.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
file->device->net->offset = off;
|
||||||
|
|
||||||
data = grub_zalloc (sizeof (*data));
|
data = grub_zalloc (sizeof (*data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
data->file_size = old_data->file_size;
|
|
||||||
data->size_recv = 1;
|
data->size_recv = 1;
|
||||||
data->filename = old_data->filename;
|
data->filename = old_data->filename;
|
||||||
if (!data->filename)
|
if (!data->filename)
|
||||||
|
@ -367,6 +435,7 @@ http_seek (struct grub_file *file, grub_off_t off)
|
||||||
}
|
}
|
||||||
grub_free (old_data);
|
grub_free (old_data);
|
||||||
|
|
||||||
|
file->data = data;
|
||||||
err = http_establish (file, off, 0);
|
err = http_establish (file, off, 0);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
|
@ -386,6 +455,7 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
data = grub_zalloc (sizeof (*data));
|
data = grub_zalloc (sizeof (*data));
|
||||||
if (!data)
|
if (!data)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
file->size = GRUB_FILE_SIZE_UNKNOWN;
|
||||||
|
|
||||||
data->filename = grub_strdup (filename);
|
data->filename = grub_strdup (filename);
|
||||||
if (!data->filename)
|
if (!data->filename)
|
||||||
|
@ -404,7 +474,6 @@ http_open (struct grub_file *file, const char *filename)
|
||||||
grub_free (data);
|
grub_free (data);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
file->size = data->file_size;
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -469,6 +469,8 @@ match_net (const grub_net_network_level_netaddress_t *net,
|
||||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||||
{
|
{
|
||||||
grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize));
|
grub_uint32_t mask = (0xffffffffU << (32 - net->ipv4.masksize));
|
||||||
|
if (net->ipv4.masksize == 0)
|
||||||
|
mask = 0;
|
||||||
return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
|
return ((grub_be_to_cpu32 (net->ipv4.base) & mask)
|
||||||
== (grub_be_to_cpu32 (addr->ipv4) & mask));
|
== (grub_be_to_cpu32 (addr->ipv4) & mask));
|
||||||
}
|
}
|
||||||
|
@ -554,6 +556,39 @@ grub_net_resolve_net_address (const char *name,
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
route_cmp (const struct grub_net_route *a, const struct grub_net_route *b)
|
||||||
|
{
|
||||||
|
if (a == NULL && b == NULL)
|
||||||
|
return 0;
|
||||||
|
if (b == NULL)
|
||||||
|
return +1;
|
||||||
|
if (a == NULL)
|
||||||
|
return -1;
|
||||||
|
if (a->target.type < b->target.type)
|
||||||
|
return -1;
|
||||||
|
if (a->target.type > b->target.type)
|
||||||
|
return +1;
|
||||||
|
switch (a->target.type)
|
||||||
|
{
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||||
|
break;
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
|
||||||
|
if (a->target.ipv6.masksize > b->target.ipv6.masksize)
|
||||||
|
return +1;
|
||||||
|
if (a->target.ipv6.masksize < b->target.ipv6.masksize)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||||
|
if (a->target.ipv4.masksize > b->target.ipv4.masksize)
|
||||||
|
return +1;
|
||||||
|
if (a->target.ipv4.masksize < b->target.ipv4.masksize)
|
||||||
|
return -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_route_address (grub_net_network_level_address_t addr,
|
grub_net_route_address (grub_net_network_level_address_t addr,
|
||||||
grub_net_network_level_address_t *gateway,
|
grub_net_network_level_address_t *gateway,
|
||||||
|
@ -572,25 +607,27 @@ grub_net_route_address (grub_net_network_level_address_t addr,
|
||||||
|
|
||||||
for (depth = 0; depth < routecnt + 2; depth++)
|
for (depth = 0; depth < routecnt + 2; depth++)
|
||||||
{
|
{
|
||||||
|
struct grub_net_route *bestroute = NULL;
|
||||||
FOR_NET_ROUTES(route)
|
FOR_NET_ROUTES(route)
|
||||||
{
|
{
|
||||||
if (depth && prot != route->prot)
|
if (depth && prot != route->prot)
|
||||||
continue;
|
continue;
|
||||||
if (!match_net (&route->target, &curtarget))
|
if (!match_net (&route->target, &curtarget))
|
||||||
continue;
|
continue;
|
||||||
|
if (route_cmp (route, bestroute) > 0)
|
||||||
if (route->is_gateway)
|
bestroute = route;
|
||||||
{
|
|
||||||
if (depth == 0)
|
|
||||||
*gateway = route->gw;
|
|
||||||
curtarget = route->gw;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*interf = route->interface;
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
}
|
||||||
if (route == NULL)
|
if (bestroute == NULL)
|
||||||
return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable");
|
return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable");
|
||||||
|
|
||||||
|
if (!bestroute->is_gateway)
|
||||||
|
{
|
||||||
|
*interf = bestroute->interface;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (depth == 0)
|
||||||
|
*gateway = bestroute->gw;
|
||||||
|
curtarget = bestroute->gw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected");
|
return grub_error (GRUB_ERR_NET_ROUTE_LOOP, "route loop detected");
|
||||||
|
@ -1285,6 +1322,7 @@ grub_net_fs_read_real (grub_file_t file, char *buf, grub_size_t len)
|
||||||
char *ptr = buf;
|
char *ptr = buf;
|
||||||
grub_size_t amount, total = 0;
|
grub_size_t amount, total = 0;
|
||||||
int try = 0;
|
int try = 0;
|
||||||
|
|
||||||
while (try <= GRUB_NET_TRIES)
|
while (try <= GRUB_NET_TRIES)
|
||||||
{
|
{
|
||||||
while (net->packs.first)
|
while (net->packs.first)
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct grub_net_tcp_socket
|
||||||
grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb,
|
grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb,
|
||||||
void *recv);
|
void *recv);
|
||||||
void (*error_hook) (grub_net_tcp_socket_t sock, void *recv);
|
void (*error_hook) (grub_net_tcp_socket_t sock, void *recv);
|
||||||
|
void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv);
|
||||||
void *hook_data;
|
void *hook_data;
|
||||||
grub_net_network_level_address_t out_nla, gw;
|
grub_net_network_level_address_t out_nla, gw;
|
||||||
struct grub_net_network_level_interface *inf;
|
struct grub_net_network_level_interface *inf;
|
||||||
|
@ -234,10 +235,20 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock,
|
||||||
struct tcphdr *tcph_fin;
|
struct tcphdr *tcph_fin;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
sock->i_closed = 1;
|
|
||||||
|
|
||||||
if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING)
|
if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING)
|
||||||
sock->recv_hook = NULL;
|
{
|
||||||
|
sock->recv_hook = NULL;
|
||||||
|
sock->error_hook = NULL;
|
||||||
|
sock->fin_hook = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discard_received == GRUB_NET_TCP_ABORT)
|
||||||
|
sock->i_reseted = 1;
|
||||||
|
|
||||||
|
if (sock->i_closed)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sock->i_closed = 1;
|
||||||
|
|
||||||
nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin)
|
nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin)
|
||||||
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
||||||
|
@ -263,13 +274,12 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
tcph_fin = (void *) nb_fin->data;
|
tcph_fin = (void *) nb_fin->data;
|
||||||
tcph_fin->ack = grub_cpu_to_be32 (0);
|
tcph_fin->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
||||||
tcph_fin->flags = grub_cpu_to_be16 ((5 << 12) | TCP_FIN);
|
tcph_fin->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN
|
||||||
tcph_fin->window = grub_cpu_to_be16 (0);
|
| TCP_ACK);
|
||||||
|
tcph_fin->window = grub_cpu_to_be16_compile_time (0);
|
||||||
tcph_fin->urgent = 0;
|
tcph_fin->urgent = 0;
|
||||||
err = tcp_send (nb_fin, sock);
|
err = tcp_send (nb_fin, sock);
|
||||||
if (discard_received == GRUB_NET_TCP_ABORT)
|
|
||||||
sock->i_reseted = 1;
|
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb_fin);
|
grub_netbuff_free (nb_fin);
|
||||||
|
@ -309,14 +319,14 @@ ack_real (grub_net_tcp_socket_t sock, int res)
|
||||||
tcph_ack = (void *) nb_ack->data;
|
tcph_ack = (void *) nb_ack->data;
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
tcph_ack->ack = grub_cpu_to_be32 (0);
|
tcph_ack->ack = grub_cpu_to_be32_compile_time (0);
|
||||||
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_RST);
|
tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST);
|
||||||
tcph_ack->window = grub_cpu_to_be16 (0);
|
tcph_ack->window = grub_cpu_to_be16_compile_time (0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
||||||
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_ACK);
|
tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
|
||||||
tcph_ack->window = grub_cpu_to_be16 (sock->my_window);
|
tcph_ack->window = grub_cpu_to_be16 (sock->my_window);
|
||||||
}
|
}
|
||||||
tcph_ack->urgent = 0;
|
tcph_ack->urgent = 0;
|
||||||
|
@ -354,6 +364,7 @@ grub_net_tcp_retransmit (void)
|
||||||
struct unacked *unack;
|
struct unacked *unack;
|
||||||
for (unack = sock->unack_first; unack; unack = unack->next)
|
for (unack = sock->unack_first; unack; unack = unack->next)
|
||||||
{
|
{
|
||||||
|
struct tcphdr *tcph;
|
||||||
grub_uint8_t *nbd;
|
grub_uint8_t *nbd;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
|
||||||
|
@ -368,6 +379,18 @@ grub_net_tcp_retransmit (void)
|
||||||
unack->try_count++;
|
unack->try_count++;
|
||||||
unack->last_try = ctime;
|
unack->last_try = ctime;
|
||||||
nbd = unack->nb->data;
|
nbd = unack->nb->data;
|
||||||
|
tcph = (struct tcphdr *) nbd;
|
||||||
|
|
||||||
|
if ((tcph->flags & grub_cpu_to_be16_compile_time (TCP_ACK))
|
||||||
|
&& tcph->ack != grub_cpu_to_be32 (sock->their_cur_seq))
|
||||||
|
{
|
||||||
|
tcph->checksum = 0;
|
||||||
|
tcph->checksum = grub_net_ip_transport_checksum (unack->nb,
|
||||||
|
GRUB_NET_IP_TCP,
|
||||||
|
&sock->inf->address,
|
||||||
|
&sock->out_nla);
|
||||||
|
}
|
||||||
|
|
||||||
err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla),
|
err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla),
|
||||||
&(sock->gw), unack->nb,
|
&(sock->gw), unack->nb,
|
||||||
GRUB_NET_IP_TCP);
|
GRUB_NET_IP_TCP);
|
||||||
|
@ -447,7 +470,10 @@ destroy_pq (grub_net_tcp_socket_t sock)
|
||||||
{
|
{
|
||||||
struct grub_net_buff **nb_p;
|
struct grub_net_buff **nb_p;
|
||||||
while ((nb_p = grub_priority_queue_top (sock->pq)))
|
while ((nb_p = grub_priority_queue_top (sock->pq)))
|
||||||
grub_netbuff_free (*nb_p);
|
{
|
||||||
|
grub_netbuff_free (*nb_p);
|
||||||
|
grub_priority_queue_pop (sock->pq);
|
||||||
|
}
|
||||||
|
|
||||||
grub_priority_queue_destroy (sock->pq);
|
grub_priority_queue_destroy (sock->pq);
|
||||||
}
|
}
|
||||||
|
@ -459,6 +485,8 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
|
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||||
|
void *data),
|
||||||
void *hook_data)
|
void *hook_data)
|
||||||
{
|
{
|
||||||
struct grub_net_buff *nb_ack;
|
struct grub_net_buff *nb_ack;
|
||||||
|
@ -467,6 +495,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
|
|
||||||
sock->recv_hook = recv_hook;
|
sock->recv_hook = recv_hook;
|
||||||
sock->error_hook = error_hook;
|
sock->error_hook = error_hook;
|
||||||
|
sock->fin_hook = fin_hook;
|
||||||
sock->hook_data = hook_data;
|
sock->hook_data = hook_data;
|
||||||
nb_ack = grub_netbuff_alloc (sizeof (*tcph)
|
nb_ack = grub_netbuff_alloc (sizeof (*tcph)
|
||||||
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
||||||
|
@ -489,7 +518,7 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
}
|
}
|
||||||
tcph = (void *) nb_ack->data;
|
tcph = (void *) nb_ack->data;
|
||||||
tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
||||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN | TCP_ACK);
|
tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN | TCP_ACK);
|
||||||
tcph->window = grub_cpu_to_be16 (sock->my_window);
|
tcph->window = grub_cpu_to_be16 (sock->my_window);
|
||||||
tcph->urgent = 0;
|
tcph->urgent = 0;
|
||||||
sock->established = 1;
|
sock->established = 1;
|
||||||
|
@ -509,6 +538,8 @@ grub_net_tcp_open (char *server,
|
||||||
void *data),
|
void *data),
|
||||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
|
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||||
|
void *data),
|
||||||
void *hook_data)
|
void *hook_data)
|
||||||
{
|
{
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
@ -548,6 +579,7 @@ grub_net_tcp_open (char *server,
|
||||||
socket->in_port = in_port++;
|
socket->in_port = in_port++;
|
||||||
socket->recv_hook = recv_hook;
|
socket->recv_hook = recv_hook;
|
||||||
socket->error_hook = error_hook;
|
socket->error_hook = error_hook;
|
||||||
|
socket->fin_hook = fin_hook;
|
||||||
socket->hook_data = hook_data;
|
socket->hook_data = hook_data;
|
||||||
|
|
||||||
nb = grub_netbuff_alloc (sizeof (*tcph) + 128);
|
nb = grub_netbuff_alloc (sizeof (*tcph) + 128);
|
||||||
|
@ -578,8 +610,8 @@ grub_net_tcp_open (char *server,
|
||||||
socket->my_cur_seq = socket->my_start_seq + 1;
|
socket->my_cur_seq = socket->my_start_seq + 1;
|
||||||
socket->my_window = 8192;
|
socket->my_window = 8192;
|
||||||
tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
|
tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
|
||||||
tcph->ack = grub_cpu_to_be32 (0);
|
tcph->ack = grub_cpu_to_be32_compile_time (0);
|
||||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN);
|
tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
|
||||||
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
||||||
tcph->urgent = 0;
|
tcph->urgent = 0;
|
||||||
tcph->src = grub_cpu_to_be16 (socket->in_port);
|
tcph->src = grub_cpu_to_be16 (socket->in_port);
|
||||||
|
@ -664,8 +696,8 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
tcph = (struct tcphdr *) nb2->data;
|
tcph = (struct tcphdr *) nb2->data;
|
||||||
tcph->ack = grub_cpu_to_be32 (0);
|
tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
|
||||||
tcph->flags = grub_cpu_to_be16 ((5 << 12));
|
tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
|
||||||
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
||||||
tcph->urgent = 0;
|
tcph->urgent = 0;
|
||||||
err = grub_netbuff_put (nb2, fraglen);
|
err = grub_netbuff_put (nb2, fraglen);
|
||||||
|
@ -686,8 +718,9 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
tcph = (struct tcphdr *) nb->data;
|
tcph = (struct tcphdr *) nb->data;
|
||||||
tcph->ack = grub_cpu_to_be32 (0);
|
tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
|
||||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | (push ? TCP_PUSH : 0));
|
tcph->flags = (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK)
|
||||||
|
| (push ? grub_cpu_to_be16_compile_time (TCP_PUSH) : 0));
|
||||||
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
||||||
tcph->urgent = 0;
|
tcph->urgent = 0;
|
||||||
return tcp_send (nb, socket);
|
return tcp_send (nb, socket);
|
||||||
|
@ -815,11 +848,15 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
|
|
||||||
err = grub_priority_queue_push (sock->pq, &nb);
|
err = grub_priority_queue_push (sock->pq, &nb);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
struct grub_net_buff **nb_top_p, *nb_top;
|
struct grub_net_buff **nb_top_p, *nb_top;
|
||||||
int do_ack = 0;
|
int do_ack = 0;
|
||||||
|
int just_closed = 0;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
nb_top_p = grub_priority_queue_top (sock->pq);
|
nb_top_p = grub_priority_queue_top (sock->pq);
|
||||||
|
@ -829,6 +866,7 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
tcph = (struct tcphdr *) nb_top->data;
|
tcph = (struct tcphdr *) nb_top->data;
|
||||||
if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq)
|
if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq)
|
||||||
break;
|
break;
|
||||||
|
grub_netbuff_free (nb_top);
|
||||||
grub_priority_queue_pop (sock->pq);
|
grub_priority_queue_pop (sock->pq);
|
||||||
}
|
}
|
||||||
if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
|
if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
|
||||||
|
@ -845,15 +883,19 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
break;
|
break;
|
||||||
grub_priority_queue_pop (sock->pq);
|
grub_priority_queue_pop (sock->pq);
|
||||||
|
|
||||||
err = grub_netbuff_pull (nb, (grub_be_to_cpu16 (tcph->flags)
|
err = grub_netbuff_pull (nb_top, (grub_be_to_cpu16 (tcph->flags)
|
||||||
>> 12) * sizeof (grub_uint32_t));
|
>> 12) * sizeof (grub_uint32_t));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
grub_netbuff_free (nb_top);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
sock->their_cur_seq += (nb_top->tail - nb_top->data);
|
sock->their_cur_seq += (nb_top->tail - nb_top->data);
|
||||||
if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
|
if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
|
||||||
{
|
{
|
||||||
sock->they_closed = 1;
|
sock->they_closed = 1;
|
||||||
|
just_closed = 1;
|
||||||
sock->their_cur_seq++;
|
sock->their_cur_seq++;
|
||||||
do_ack = 1;
|
do_ack = 1;
|
||||||
}
|
}
|
||||||
|
@ -868,14 +910,19 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
||||||
}
|
}
|
||||||
if (do_ack)
|
if (do_ack)
|
||||||
ack (sock);
|
ack (sock);
|
||||||
|
while (sock->packs.first)
|
||||||
|
{
|
||||||
|
nb = sock->packs.first->nb;
|
||||||
|
if (sock->recv_hook)
|
||||||
|
sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data);
|
||||||
|
else
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
grub_net_remove_packet (sock->packs.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock->fin_hook && just_closed)
|
||||||
|
sock->fin_hook (sock, sock->hook_data);
|
||||||
}
|
}
|
||||||
while (sock->packs.first)
|
|
||||||
{
|
|
||||||
nb = sock->packs.first->nb;
|
|
||||||
if (sock->recv_hook)
|
|
||||||
sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data);
|
|
||||||
grub_net_remove_packet (sock->packs.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ grub_net_tcp_open (char *server,
|
||||||
void *data),
|
void *data),
|
||||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
|
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||||
|
void *data),
|
||||||
void *hook_data);
|
void *hook_data);
|
||||||
|
|
||||||
grub_net_tcp_listen_t
|
grub_net_tcp_listen_t
|
||||||
|
@ -70,6 +72,8 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||||
void *data),
|
void *data),
|
||||||
|
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||||
|
void *data),
|
||||||
void *hook_data);
|
void *hook_data);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -214,6 +214,7 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
|
||||||
# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
|
# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
|
||||||
# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
|
# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
|
||||||
# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
|
# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
|
||||||
|
# define grub_cpu_to_be16_compile_time(x) ((grub_uint16_t) (x))
|
||||||
# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x))
|
# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x))
|
||||||
# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x))
|
# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x))
|
||||||
# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x))
|
# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x))
|
||||||
|
@ -232,6 +233,7 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
|
||||||
# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
|
# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
|
||||||
# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
|
# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
|
||||||
# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
|
# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
|
||||||
|
# define grub_cpu_to_be16_compile_time(x) grub_swap_bytes16_compile_time(x)
|
||||||
# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x)
|
# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x)
|
||||||
# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
||||||
# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
||||||
|
|
Loading…
Reference in a new issue