check option length when processing TCP options.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20774 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -236,49 +236,49 @@ process_options(tcp_segment_header &segment, net_buffer *buffer, int32 size)
|
|||||||
uint8 optionsBuffer[32];
|
uint8 optionsBuffer[32];
|
||||||
if (gBufferModule->direct_access(buffer, sizeof(tcp_header), size,
|
if (gBufferModule->direct_access(buffer, sizeof(tcp_header), size,
|
||||||
(void **)&option) != B_OK) {
|
(void **)&option) != B_OK) {
|
||||||
if (size > 32) {
|
if (size > 32)
|
||||||
dprintf("options too large to take into account (%ld bytes)\n", size);
|
panic("UNIMPLEMENTED: TCP option processing across data nodes");
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
|
gBufferModule->read(buffer, sizeof(tcp_header), optionsBuffer, size);
|
||||||
option = (tcp_option *)optionsBuffer;
|
option = (tcp_option *)optionsBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
uint32 length = 1;
|
int32 length = -1;
|
||||||
|
|
||||||
switch (option->kind) {
|
switch (option->kind) {
|
||||||
case TCP_OPTION_END:
|
case TCP_OPTION_END:
|
||||||
case TCP_OPTION_NOP:
|
case TCP_OPTION_NOP:
|
||||||
|
length = 1;
|
||||||
break;
|
break;
|
||||||
case TCP_OPTION_MAX_SEGMENT_SIZE:
|
case TCP_OPTION_MAX_SEGMENT_SIZE:
|
||||||
segment.max_segment_size = ntohs(option->max_segment_size);
|
if (option->length == 4 && (size - 4) >= 0)
|
||||||
length = 4;
|
segment.max_segment_size = ntohs(option->max_segment_size);
|
||||||
break;
|
break;
|
||||||
case TCP_OPTION_WINDOW_SHIFT:
|
case TCP_OPTION_WINDOW_SHIFT:
|
||||||
segment.has_window_shift = true;
|
if (option->length == 3 && (size - 3) >= 0) {
|
||||||
segment.window_shift = option->window_shift;
|
segment.has_window_shift = true;
|
||||||
length = 3;
|
segment.window_shift = option->window_shift;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TCP_OPTION_TIMESTAMP:
|
case TCP_OPTION_TIMESTAMP:
|
||||||
segment.has_timestamps = true;
|
if (option->length == 10 && (size - 10) >= 0) {
|
||||||
segment.TSval = option->timestamp.TSval;
|
segment.has_timestamps = true;
|
||||||
segment.TSecr = ntohl(option->timestamp.TSecr);
|
segment.TSval = option->timestamp.TSval;
|
||||||
length = 10;
|
segment.TSecr = ntohl(option->timestamp.TSecr);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
if (length < 0) {
|
||||||
length = option->length;
|
length = option->length;
|
||||||
// make sure we don't end up in an endless loop
|
if (length == 0)
|
||||||
if (length == 0)
|
|
||||||
return;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size -= length;
|
size -= length;
|
||||||
option = (tcp_option *)((uint8 *)option + length);
|
option = (tcp_option *)((uint8 *)option + length);
|
||||||
}
|
}
|
||||||
// TODO: check if options are valid!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user