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_size_t block_size;
|
||||
grub_size_t buffer_len;
|
||||
grub_off_t buffer_at;
|
||||
char buffer[0];
|
||||
};
|
||||
typedef struct grub_bufio *grub_bufio_t;
|
||||
|
@ -70,6 +71,7 @@ grub_bufio_open (grub_file_t io, int size)
|
|||
bufio->file = io;
|
||||
bufio->block_size = size;
|
||||
bufio->buffer_len = 0;
|
||||
bufio->buffer_at = 0;
|
||||
|
||||
file->device = io->device;
|
||||
file->offset = 0;
|
||||
|
@ -104,82 +106,86 @@ grub_buffile_open (const char *name, int size)
|
|||
static grub_ssize_t
|
||||
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_uint64_t pos;
|
||||
|
||||
if ((file->offset >= bufio->file->offset) &&
|
||||
(file->offset < bufio->file->offset + bufio->buffer_len))
|
||||
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
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_uint64_t pos;
|
||||
|
||||
pos = file->offset - bufio->file->offset;
|
||||
pos = file->offset - bufio->buffer_at;
|
||||
n = bufio->buffer_len - pos;
|
||||
if (n > len)
|
||||
n = len;
|
||||
|
||||
grub_memcpy (buf, &bufio->buffer[pos], n);
|
||||
len -= n;
|
||||
res += n;
|
||||
|
||||
buf += n;
|
||||
}
|
||||
if (! len)
|
||||
return res;
|
||||
|
||||
buf += n;
|
||||
bufio->file->offset += bufio->buffer_len;
|
||||
pos = 0;
|
||||
}
|
||||
else
|
||||
/* 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)
|
||||
{
|
||||
bufio->file->offset = grub_divmod64 (file->offset, bufio->block_size,
|
||||
&pos);
|
||||
bufio->file->offset *= bufio->block_size;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (pos + len >= bufio->block_size)
|
||||
{
|
||||
if (pos)
|
||||
{
|
||||
grub_size_t n;
|
||||
|
||||
bufio->file->fs->read (bufio->file, bufio->buffer,
|
||||
/* 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;
|
||||
|
||||
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)
|
||||
if (len < bufio->buffer_len)
|
||||
{
|
||||
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;
|
||||
grub_memcpy (buf, &bufio->buffer[0], len);
|
||||
res += len;
|
||||
}
|
||||
|
||||
if (! len)
|
||||
else
|
||||
{
|
||||
bufio->buffer_len = 0;
|
||||
return res;
|
||||
grub_memcpy (buf, &bufio->buffer[0], bufio->buffer_len);
|
||||
res += bufio->buffer_len;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
{
|
||||
|
@ -468,9 +469,11 @@ grub_disk_read_small (grub_disk_t disk, grub_disk_addr_t sector,
|
|||
grub_error_push ();
|
||||
grub_dprintf ("disk", "%s read failed\n", disk->name);
|
||||
grub_error_pop ();
|
||||
grub_free (tmp_buf);
|
||||
return grub_errno;
|
||||
}
|
||||
grub_memcpy (buf, tmp_buf + offset, size);
|
||||
grub_free (tmp_buf);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,22 @@ parse_dhcp_vendor (const char *name, void *vend, int limit)
|
|||
|
||||
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:
|
||||
set_env_limn_ro (name, "hostname", (char *) ptr, taglength);
|
||||
break;
|
||||
|
|
|
@ -36,8 +36,6 @@ enum
|
|||
|
||||
typedef struct http_data
|
||||
{
|
||||
grub_uint64_t file_size;
|
||||
grub_uint64_t position;
|
||||
char *current_line;
|
||||
grub_size_t current_line_len;
|
||||
int headers_recv;
|
||||
|
@ -47,18 +45,53 @@ typedef struct http_data
|
|||
char *filename;
|
||||
grub_err_t err;
|
||||
char *errmsg;
|
||||
int chunked;
|
||||
grub_size_t chunk_rem;
|
||||
int in_chunk_len;
|
||||
} *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
|
||||
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;
|
||||
while (end > ptr && *(end - 1) == '\r')
|
||||
end--;
|
||||
*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)
|
||||
{
|
||||
data->headers_recv = 1;
|
||||
if (data->chunked)
|
||||
data->in_chunk_len = 2;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -93,10 +126,17 @@ parse_line (http_data_t data, char *ptr, grub_size_t len)
|
|||
== 0 && !data->size_recv)
|
||||
{
|
||||
ptr += sizeof ("Content-Length: ") - 1;
|
||||
data->file_size = grub_strtoull (ptr, &ptr, 10);
|
||||
file->size = grub_strtoull (ptr, &ptr, 10);
|
||||
data->size_recv = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -113,6 +153,8 @@ http_err (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
grub_free (data->current_line);
|
||||
grub_free (data);
|
||||
file->device->net->eof = 1;
|
||||
if (file->size == GRUB_FILE_SIZE_UNKNOWN)
|
||||
file->size = have_ahead (file);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
@ -122,10 +164,12 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
{
|
||||
grub_file_t file = f;
|
||||
http_data_t data = file->data;
|
||||
char *ptr = (char *) nb->data;
|
||||
grub_err_t err;
|
||||
|
||||
if (!data->headers_recv && data->current_line)
|
||||
while (1)
|
||||
{
|
||||
char *ptr = (char *) nb->data;
|
||||
if ((!data->headers_recv || data->in_chunk_len) && data->current_line)
|
||||
{
|
||||
int have_line = 1;
|
||||
char *t;
|
||||
|
@ -155,7 +199,8 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
err = parse_line (data, data->current_line, data->current_line_len);
|
||||
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;
|
||||
|
@ -167,7 +212,8 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
}
|
||||
}
|
||||
|
||||
while (ptr < (char *) nb->tail && !data->headers_recv)
|
||||
while (ptr < (char *) nb->tail && (!data->headers_recv
|
||||
|| data->in_chunk_len))
|
||||
{
|
||||
char *ptr2;
|
||||
ptr2 = grub_memchr (ptr, '\n', (char *) nb->tail - ptr);
|
||||
|
@ -185,7 +231,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
err = parse_line (data, ptr, ptr2 - ptr);
|
||||
err = parse_line (file, data, ptr, ptr2 - ptr);
|
||||
if (err)
|
||||
{
|
||||
grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||
|
@ -195,9 +241,11 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
ptr = ptr2 + 1;
|
||||
}
|
||||
|
||||
if (((char *) nb->tail - ptr) > 0)
|
||||
if (((char *) nb->tail - ptr) <= 0)
|
||||
{
|
||||
data->position += ((char *) nb->tail - ptr);
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
err = grub_netbuff_pull (nb, ptr - (char *) nb->data);
|
||||
if (err)
|
||||
{
|
||||
|
@ -205,12 +253,28 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
|||
grub_netbuff_free (nb);
|
||||
return err;
|
||||
}
|
||||
if (!(data->chunked && (grub_ssize_t) data->chunk_rem
|
||||
< nb->tail - nb->data))
|
||||
{
|
||||
grub_net_put_packet (&file->device->net->packs, nb);
|
||||
}
|
||||
else
|
||||
grub_netbuff_free (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;
|
||||
}
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||
|
@ -294,7 +358,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
|||
"\r\n"),
|
||||
"Content-Range: bytes %" PRIuGRUB_UINT64_T "-%"
|
||||
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));
|
||||
}
|
||||
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,
|
||||
HTTP_PORT, http_receive,
|
||||
http_err,
|
||||
http_err, http_err,
|
||||
file);
|
||||
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);
|
||||
|
||||
while (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));
|
||||
if (!data)
|
||||
return grub_errno;
|
||||
|
||||
data->file_size = old_data->file_size;
|
||||
data->size_recv = 1;
|
||||
data->filename = old_data->filename;
|
||||
if (!data->filename)
|
||||
|
@ -367,6 +435,7 @@ http_seek (struct grub_file *file, grub_off_t off)
|
|||
}
|
||||
grub_free (old_data);
|
||||
|
||||
file->data = data;
|
||||
err = http_establish (file, off, 0);
|
||||
if (err)
|
||||
{
|
||||
|
@ -386,6 +455,7 @@ http_open (struct grub_file *file, const char *filename)
|
|||
data = grub_zalloc (sizeof (*data));
|
||||
if (!data)
|
||||
return grub_errno;
|
||||
file->size = GRUB_FILE_SIZE_UNKNOWN;
|
||||
|
||||
data->filename = grub_strdup (filename);
|
||||
if (!data->filename)
|
||||
|
@ -404,7 +474,6 @@ http_open (struct grub_file *file, const char *filename)
|
|||
grub_free (data);
|
||||
return err;
|
||||
}
|
||||
file->size = data->file_size;
|
||||
|
||||
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:
|
||||
{
|
||||
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)
|
||||
== (grub_be_to_cpu32 (addr->ipv4) & mask));
|
||||
}
|
||||
|
@ -554,6 +556,39 @@ grub_net_resolve_net_address (const char *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_net_route_address (grub_net_network_level_address_t addr,
|
||||
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++)
|
||||
{
|
||||
struct grub_net_route *bestroute = NULL;
|
||||
FOR_NET_ROUTES(route)
|
||||
{
|
||||
if (depth && prot != route->prot)
|
||||
continue;
|
||||
if (!match_net (&route->target, &curtarget))
|
||||
continue;
|
||||
|
||||
if (route->is_gateway)
|
||||
{
|
||||
if (depth == 0)
|
||||
*gateway = route->gw;
|
||||
curtarget = route->gw;
|
||||
break;
|
||||
if (route_cmp (route, bestroute) > 0)
|
||||
bestroute = route;
|
||||
}
|
||||
*interf = route->interface;
|
||||
if (bestroute == NULL)
|
||||
return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable");
|
||||
|
||||
if (!bestroute->is_gateway)
|
||||
{
|
||||
*interf = bestroute->interface;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (route == NULL)
|
||||
return grub_error (GRUB_ERR_NET_NO_ROUTE, "destination unreachable");
|
||||
if (depth == 0)
|
||||
*gateway = bestroute->gw;
|
||||
curtarget = bestroute->gw;
|
||||
}
|
||||
|
||||
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;
|
||||
grub_size_t amount, total = 0;
|
||||
int try = 0;
|
||||
|
||||
while (try <= GRUB_NET_TRIES)
|
||||
{
|
||||
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,
|
||||
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;
|
||||
grub_net_network_level_address_t out_nla, gw;
|
||||
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;
|
||||
grub_err_t err;
|
||||
|
||||
sock->i_closed = 1;
|
||||
|
||||
if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING)
|
||||
{
|
||||
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)
|
||||
+ GRUB_NET_OUR_MAX_IP_HEADER_SIZE
|
||||
|
@ -263,13 +274,12 @@ grub_net_tcp_close (grub_net_tcp_socket_t sock,
|
|||
return;
|
||||
}
|
||||
tcph_fin = (void *) nb_fin->data;
|
||||
tcph_fin->ack = grub_cpu_to_be32 (0);
|
||||
tcph_fin->flags = grub_cpu_to_be16 ((5 << 12) | TCP_FIN);
|
||||
tcph_fin->window = grub_cpu_to_be16 (0);
|
||||
tcph_fin->ack = grub_cpu_to_be32 (sock->their_cur_seq);
|
||||
tcph_fin->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN
|
||||
| TCP_ACK);
|
||||
tcph_fin->window = grub_cpu_to_be16_compile_time (0);
|
||||
tcph_fin->urgent = 0;
|
||||
err = tcp_send (nb_fin, sock);
|
||||
if (discard_received == GRUB_NET_TCP_ABORT)
|
||||
sock->i_reseted = 1;
|
||||
if (err)
|
||||
{
|
||||
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;
|
||||
if (res)
|
||||
{
|
||||
tcph_ack->ack = grub_cpu_to_be32 (0);
|
||||
tcph_ack->flags = grub_cpu_to_be16 ((5 << 12) | TCP_RST);
|
||||
tcph_ack->window = grub_cpu_to_be16 (0);
|
||||
tcph_ack->ack = grub_cpu_to_be32_compile_time (0);
|
||||
tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST);
|
||||
tcph_ack->window = grub_cpu_to_be16_compile_time (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
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->urgent = 0;
|
||||
|
@ -354,6 +364,7 @@ grub_net_tcp_retransmit (void)
|
|||
struct unacked *unack;
|
||||
for (unack = sock->unack_first; unack; unack = unack->next)
|
||||
{
|
||||
struct tcphdr *tcph;
|
||||
grub_uint8_t *nbd;
|
||||
grub_err_t err;
|
||||
|
||||
|
@ -368,6 +379,18 @@ grub_net_tcp_retransmit (void)
|
|||
unack->try_count++;
|
||||
unack->last_try = ctime;
|
||||
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),
|
||||
&(sock->gw), unack->nb,
|
||||
GRUB_NET_IP_TCP);
|
||||
|
@ -447,7 +470,10 @@ destroy_pq (grub_net_tcp_socket_t sock)
|
|||
{
|
||||
struct grub_net_buff **nb_p;
|
||||
while ((nb_p = grub_priority_queue_top (sock->pq)))
|
||||
{
|
||||
grub_netbuff_free (*nb_p);
|
||||
grub_priority_queue_pop (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 (*error_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void *hook_data)
|
||||
{
|
||||
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->error_hook = error_hook;
|
||||
sock->fin_hook = fin_hook;
|
||||
sock->hook_data = hook_data;
|
||||
nb_ack = grub_netbuff_alloc (sizeof (*tcph)
|
||||
+ 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->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->urgent = 0;
|
||||
sock->established = 1;
|
||||
|
@ -509,6 +538,8 @@ grub_net_tcp_open (char *server,
|
|||
void *data),
|
||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void *hook_data)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
@ -548,6 +579,7 @@ grub_net_tcp_open (char *server,
|
|||
socket->in_port = in_port++;
|
||||
socket->recv_hook = recv_hook;
|
||||
socket->error_hook = error_hook;
|
||||
socket->fin_hook = fin_hook;
|
||||
socket->hook_data = hook_data;
|
||||
|
||||
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_window = 8192;
|
||||
tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
|
||||
tcph->ack = grub_cpu_to_be32 (0);
|
||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | TCP_SYN);
|
||||
tcph->ack = grub_cpu_to_be32_compile_time (0);
|
||||
tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
|
||||
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
||||
tcph->urgent = 0;
|
||||
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;
|
||||
|
||||
tcph = (struct tcphdr *) nb2->data;
|
||||
tcph->ack = grub_cpu_to_be32 (0);
|
||||
tcph->flags = grub_cpu_to_be16 ((5 << 12));
|
||||
tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
|
||||
tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
|
||||
tcph->window = grub_cpu_to_be16 (socket->my_window);
|
||||
tcph->urgent = 0;
|
||||
err = grub_netbuff_put (nb2, fraglen);
|
||||
|
@ -686,8 +718,9 @@ grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
|
|||
return err;
|
||||
|
||||
tcph = (struct tcphdr *) nb->data;
|
||||
tcph->ack = grub_cpu_to_be32 (0);
|
||||
tcph->flags = grub_cpu_to_be16 ((5 << 12) | (push ? TCP_PUSH : 0));
|
||||
tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
|
||||
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->urgent = 0;
|
||||
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);
|
||||
if (err)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return err;
|
||||
}
|
||||
|
||||
{
|
||||
struct grub_net_buff **nb_top_p, *nb_top;
|
||||
int do_ack = 0;
|
||||
int just_closed = 0;
|
||||
while (1)
|
||||
{
|
||||
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;
|
||||
if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq)
|
||||
break;
|
||||
grub_netbuff_free (nb_top);
|
||||
grub_priority_queue_pop (sock->pq);
|
||||
}
|
||||
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;
|
||||
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));
|
||||
if (err)
|
||||
{
|
||||
grub_netbuff_free (nb_top);
|
||||
return err;
|
||||
}
|
||||
|
||||
sock->their_cur_seq += (nb_top->tail - nb_top->data);
|
||||
if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
|
||||
{
|
||||
sock->they_closed = 1;
|
||||
just_closed = 1;
|
||||
sock->their_cur_seq++;
|
||||
do_ack = 1;
|
||||
}
|
||||
|
@ -868,15 +910,20 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
|||
}
|
||||
if (do_ack)
|
||||
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);
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (grub_be_to_cpu16 (tcph->flags) & TCP_SYN)
|
||||
|
|
|
@ -35,6 +35,8 @@ grub_net_tcp_open (char *server,
|
|||
void *data),
|
||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void *hook_data);
|
||||
|
||||
grub_net_tcp_listen_t
|
||||
|
@ -70,6 +72,8 @@ grub_net_tcp_accept (grub_net_tcp_socket_t sock,
|
|||
void *data),
|
||||
void (*error_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void (*fin_hook) (grub_net_tcp_socket_t sock,
|
||||
void *data),
|
||||
void *hook_data);
|
||||
|
||||
#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_cpu32(x) ((grub_uint32_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_be64_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_cpu32(x) grub_swap_bytes32(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_be64_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