pcap: fix several segfaults with NULL pcap file handle

- pcap_open did not return NULL if fopen failed
- libfreerdp-core, tfreerdp-serer and xfreerdp-server did not check the pcap_open result
- also fixed the sleep calculation in the xfreerdp-server
This commit is contained in:
Norbert Federa 2011-10-20 14:25:25 +02:00
parent 5f7aafd7aa
commit 12245abfc8
5 changed files with 70 additions and 22 deletions

View File

@ -42,8 +42,9 @@ boolean freerdp_connect(freerdp* instance)
{ {
if (instance->settings->dump_rfx) if (instance->settings->dump_rfx)
{ {
instance->update->dump_rfx = instance->settings->dump_rfx;
instance->update->pcap_rfx = pcap_open(instance->settings->dump_rfx_file, True); instance->update->pcap_rfx = pcap_open(instance->settings->dump_rfx_file, True);
if (instance->update->pcap_rfx)
instance->update->dump_rfx = True;
} }
IFCALL(instance->PostConnect, instance); IFCALL(instance->PostConnect, instance);
@ -55,11 +56,12 @@ boolean freerdp_connect(freerdp* instance)
pcap_record record; pcap_record record;
s = stream_new(1024); s = stream_new(1024);
instance->update->play_rfx = instance->settings->play_rfx;
instance->update->pcap_rfx = pcap_open(instance->settings->play_rfx_file, False); instance->update->pcap_rfx = pcap_open(instance->settings->play_rfx_file, False);
if (instance->update->pcap_rfx)
instance->update->play_rfx = True;
update = instance->update; update = instance->update;
while (pcap_has_next_record(update->pcap_rfx)) while (instance->update->play_rfx && pcap_has_next_record(update->pcap_rfx))
{ {
pcap_get_next_record_header(update->pcap_rfx, &record); pcap_get_next_record_header(update->pcap_rfx, &record);

View File

@ -134,6 +134,13 @@ rdpPcap* pcap_open(char* name, boolean write)
{ {
rdpPcap* pcap; rdpPcap* pcap;
FILE *pcap_fp = fopen(name, write ? "w+" : "r");
if (pcap_fp == NULL)
{
perror("opening pcap dump");
return NULL;
}
pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap)); pcap = (rdpPcap*) xzalloc(sizeof(rdpPcap));
if (pcap != NULL) if (pcap != NULL)
@ -141,10 +148,10 @@ rdpPcap* pcap_open(char* name, boolean write)
pcap->name = name; pcap->name = name;
pcap->write = write; pcap->write = write;
pcap->record_count = 0; pcap->record_count = 0;
pcap->fp = pcap_fp;
if (write) if (write)
{ {
pcap->fp = fopen(name, "w+");
pcap->header.magic_number = 0xA1B2C3D4; pcap->header.magic_number = 0xA1B2C3D4;
pcap->header.version_major = 2; pcap->header.version_major = 2;
pcap->header.version_minor = 4; pcap->header.version_minor = 4;
@ -156,7 +163,6 @@ rdpPcap* pcap_open(char* name, boolean write)
} }
else else
{ {
pcap->fp = fopen(name, "r");
fseek(pcap->fp, 0, SEEK_END); fseek(pcap->fp, 0, SEEK_END);
pcap->file_size = (int) ftell(pcap->fp); pcap->file_size = (int) ftell(pcap->fp);
fseek(pcap->fp, 0, SEEK_SET); fseek(pcap->fp, 0, SEEK_SET);

View File

@ -27,6 +27,7 @@
#include <freerdp/codec/color.h> #include <freerdp/codec/color.h>
extern char* xf_pcap_file; extern char* xf_pcap_file;
extern boolean xf_pcap_dump_realtime;
#include "xf_encode.h" #include "xf_encode.h"
@ -49,7 +50,10 @@ xfInfo* xf_info_init()
xfi->display = XOpenDisplay(NULL); xfi->display = XOpenDisplay(NULL);
if (xfi->display == NULL) if (xfi->display == NULL)
{
printf("failed to open display: %s\n", XDisplayName(NULL)); printf("failed to open display: %s\n", XDisplayName(NULL));
exit(1);
}
xfi->number = DefaultScreen(xfi->display); xfi->number = DefaultScreen(xfi->display);
xfi->screen = ScreenOfDisplay(xfi->display, xfi->number); xfi->screen = ScreenOfDisplay(xfi->display, xfi->number);
@ -227,12 +231,49 @@ void xf_peer_live_rfx(freerdp_peer* client)
} }
} }
static boolean xf_peer_sleep_tsdiff(uint32 *old_sec, uint32 *old_usec, uint32 new_sec, uint32 new_usec)
{
sint32 sec, usec;
if (*old_sec==0 && *old_usec==0)
{
*old_sec = new_sec;
*old_usec = new_usec;
return True;
}
sec = new_sec - *old_sec;
usec = new_usec - *old_usec;
if (sec<0 || (sec==0 && usec<0))
{
printf("Invalid time stamp detected.\n");
return False;
}
*old_sec = new_sec;
*old_usec = new_usec;
while (usec < 0)
{
usec += 1000000;
sec--;
}
if (sec > 0)
freerdp_sleep(sec);
if (usec > 0)
freerdp_usleep(usec);
return True;
}
void xf_peer_dump_rfx(freerdp_peer* client) void xf_peer_dump_rfx(freerdp_peer* client)
{ {
STREAM* s; STREAM* s;
double ttime; uint32 prev_seconds;
uint32 seconds; uint32 prev_useconds;
uint32 useconds;
rdpUpdate* update; rdpUpdate* update;
rdpPcap* pcap_rfx; rdpPcap* pcap_rfx;
pcap_record record; pcap_record record;
@ -242,7 +283,10 @@ void xf_peer_dump_rfx(freerdp_peer* client)
client->update->pcap_rfx = pcap_open(xf_pcap_file, False); client->update->pcap_rfx = pcap_open(xf_pcap_file, False);
pcap_rfx = client->update->pcap_rfx; pcap_rfx = client->update->pcap_rfx;
seconds = useconds = 0; if (pcap_rfx == NULL)
return;
prev_seconds = prev_useconds = 0;
while (pcap_has_next_record(pcap_rfx)) while (pcap_has_next_record(pcap_rfx))
{ {
@ -255,19 +299,8 @@ void xf_peer_dump_rfx(freerdp_peer* client)
pcap_get_next_record_content(pcap_rfx, &record); pcap_get_next_record_content(pcap_rfx, &record);
s->p = s->data + s->size; s->p = s->data + s->size;
seconds = record.header.ts_sec - seconds; if (xf_pcap_dump_realtime && xf_peer_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == False)
useconds = record.header.ts_usec - useconds; break;
ttime = ((double) seconds * 1000000) + (double) useconds;
seconds = (uint32) (ttime / 1000000);
useconds = (uint32) (ttime - (((double) seconds) * 1000000));
if (seconds > 0)
freerdp_sleep(seconds);
if (useconds > 0)
freerdp_usleep(useconds);
update->SurfaceCommand(update, s); update->SurfaceCommand(update, s);
} }

View File

@ -26,6 +26,7 @@
#include "xfreerdp.h" #include "xfreerdp.h"
char* xf_pcap_file = NULL; char* xf_pcap_file = NULL;
boolean xf_pcap_dump_realtime = True;
void xf_server_main_loop(freerdp_listener* instance) void xf_server_main_loop(freerdp_listener* instance)
{ {
@ -100,6 +101,9 @@ int main(int argc, char* argv[])
if (argc > 1) if (argc > 1)
xf_pcap_file = argv[1]; xf_pcap_file = argv[1];
if (argc > 2 && !strcmp(argv[2], "--fast"))
xf_pcap_dump_realtime = False;
/* Open the server socket and start listening. */ /* Open the server socket and start listening. */
if (instance->Open(instance, NULL, 3389)) if (instance->Open(instance, NULL, 3389))
{ {

View File

@ -299,6 +299,9 @@ void tf_peer_dump_rfx(freerdp_peer* client)
client->update->pcap_rfx = pcap_open(test_pcap_file, False); client->update->pcap_rfx = pcap_open(test_pcap_file, False);
pcap_rfx = client->update->pcap_rfx; pcap_rfx = client->update->pcap_rfx;
if (pcap_rfx == NULL)
return;
prev_seconds = prev_useconds = 0; prev_seconds = prev_useconds = 0;
while (pcap_has_next_record(pcap_rfx)) while (pcap_has_next_record(pcap_rfx))