driftnet stable port information

Package: driftnet
Version: 0.1.6
Revision: 1025
Maintainer: H. Todd Fujinaka
Depends: libpcap-shlibs, libpng3-shlibs, pango1-xft2-ft219-shlibs (>= 1.18.4-4), libjpeg-shlibs, libiconv, gtk+2-shlibs (>= 2.12.0-1), glib2-shlibs (>= 2.14.0-1), atk1-shlibs (>= 1.20.0-1), giflib-shlibs, x11, libgettext3-shlibs
BuildDepends: glitz, expat1, cairo (>= 1.6-1), fontconfig2-dev (>= 2.4.1-1), freetype219 (>= 2.3.5-1), xft2-dev, libpcap, libpng3, pango1-xft2-ft219-dev (>= 1.18.4-4), pixman (>= 0.10.0-1), libjpeg, libiconv-dev, gtk+2-dev (>= 2.12.0-1), glib2-dev (>= 2.14.0-1), atk1 (>= 1.20.0-1), giflib, x11-dev, libgettext3-dev, pkgconfig (>= 0.21-1)
Replaces: drifnet
Source: http://www.ex-parrot.com/~chris/driftnet/driftnet-%v.tar.gz
Source-MD5: 8e11d77770452f97bb3c23f510489815
PatchScript: <<
#!/bin/sh -ev
sed 's:@PREFIX@:%p:g' <%a/%{n}.patch | patch -p1
<<
NoSetMAKEFLAGS: true
SetMAKEFLAGS: -j1
CompileScript: make PKG_CONFIG_PATH="%p/lib/pango-ft219/lib/pkgconfig:%p/lib/fontconfig2/lib/pkgconfig:%p/lib/freetype219/lib/pkgconfig:$PKG_CONFIG_PATH" FREETYPE_CONFIG=%p/lib/freetype219/bin/freetype-config
InstallScript: <<
#!/bin/sh -ev
install -d -m 755 %i/bin
install -m 755 driftnet %i/bin
install -d -m 755 %i/share/man/man1
install -m 755 driftnet.1 %i/share/man/man1
<<
DocFiles: CHANGES COPYING README CREDITS TODO
Description: Tool for snooping pictures
DescDetail: <<
Driftnet watches network traffic, and picks out and displays JPEG and GIF
images for display. It is an horrific invasion of privacy and shouldn't be used
by anyone anywhere. It can also extract MPEG audio data from the network and
play it. If you live in a house with thick walls, this may be a useful way to
find out about your neighbours' musical taste.
<<
DescUsage: <<
sudo ./driftnet
<<
License: GPL
Homepage: http://www.ex-parrot.com/~chris/driftnet/

driftnet stable port .patch

diff -Naur driftnet-0.1.6/CHANGES driftnet/CHANGES
--- driftnet-0.1.6/CHANGES Tue Jul 9 12:26:41 2002
+++ driftnet/CHANGES Mon Apr 26 07:42:36 2004
@@ -1,5 +1,16 @@
Changelog for driftnet
-$Id: CHANGES,v 1.16 2002/07/09 17:31:00 chris Exp $
+$Id: CHANGES,v 1.19 2004/04/26 14:42:36 chris Exp $
+
+Driftnet now uses GTK2, rather than GTK1.
+
+Added support for reading packets from a pcap dump file (thanks to Rob Timko
+and Joshua Wright for this); and for extracting URLs from HTTP requests (not
+yet exposed in the user interface).
+
+Driftnet will now discard connections after 8Mb of data has been transferred.
+
+Fixed adjunct mode so that stdout is line-buffered, following a suggestion by
+Jonas Jensen.

0.1.6

diff -Naur driftnet-0.1.6/CREDITS driftnet/CREDITS
--- driftnet-0.1.6/CREDITS Tue Jul 9 12:26:41 2002
+++ driftnet/CREDITS Mon Apr 26 07:42:36 2004
@@ -1,5 +1,5 @@
Credits and contributors for driftnet
-$Id: CREDITS,v 1.6 2002/06/10 21:25:48 chris Exp $
+$Id: CREDITS,v 1.9 2004/04/26 14:42:36 chris Exp $

Thanks to the authors of EtherPEG, for a cool idea, and to Eric Richardson,
whose website brought it to my attention.
@@ -11,4 +11,13 @@

Eric Dobbs for fixing some portability issues and getting driftnet running on
Solaris and BSD systems.
+
+Drew Roedersheimer for contributing PNG support.
+
+Joshua Wright for some 802.11 fixes.
+
+Rob Timko and Joshua Wright for getting Driftnet working on wireless networks
+and reading decrypted data from Kismet.
+
+Bastien Nocera for updating driftnet to use GTK2.

diff -Naur driftnet-0.1.6/Makefile driftnet/Makefile
--- driftnet-0.1.6/Makefile Tue Aug 24 20:33:35 2004
+++ driftnet/Makefile Sat Aug 28 23:36:16 2004
@@ -5,7 +5,7 @@
# Copyright (c) 2001 Chris Lightfoot. All rights reserved.
# Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
#
-# $Id: Makefile,v 1.34 2002/07/09 17:30:42 chris Exp $
+# $Id: Makefile,v 1.41 2004/04/26 14:42:36 chris Exp $
#

#
@@ -20,19 +20,23 @@
LDFLAGS += -g

# You might need these if libpcap is installed somewhere random.
-CFLAGS += -I/usr/include/pcap
+#CFLAGS += -I/usr/include/pcap
#LDFLAGS += -L/path/to/libpcap.so
+# On Mac OS X with Fink etc., try these:
+CFLAGS += -I/usr/include/pcap -I@PREFIX@/include # -I/opt/local/include
+LDFLAGS += -L@PREFIX@/lib/
+#LDFLAGS += -L/opt/local/lib/

# Required on Linux to get BSDish definitions of the TCP/IP structs.
CFLAGS += -D_BSD_SOURCE

# We always need the pcap and pthread libraries.
-LDLIBS += -lpcap -lpthread
+LDLIBS += -lpcap -lpthread #-lefence

# Optional C compiler and linker flags. Typical driftnet builds have support
# for displaying captured images in an X window, and need the following flags:
-CFLAGS += `gtk-config --cflags`
-LDLIBS += -ljpeg -lungif `gtk-config --libs`
+CFLAGS += `pkg-config --cflags gtk+-2.0`
+LDLIBS += -ljpeg -lgif -lpng `pkg-config --libs gtk+-2.0`

# Alternatively, you can build a version of driftnet which can only be used
# in `adjunct' mode as the back end for some other image-processing program. To
@@ -49,7 +53,6 @@
# nanosleep; uncomment the below.
#LDLIBS += -lposix4

-# added 20020604 edobbs
# On BSD systems, may need to use /usr/local/include
#CFLAGS += -I/usr/local/include

@@ -66,7 +69,7 @@

TXTS = README TODO COPYING CHANGES CREDITS driftnet.1 driftnet.1.in endian.c
SRCS = audio.c mpeghdr.c gif.c img.c jpeg.c png.c driftnet.c image.c \
- display.c playaudio.c connection.c media.c
+ display.c playaudio.c connection.c media.c util.c http.c
HDRS = img.h driftnet.h mpeghdr.h
BINS = driftnet

@@ -80,17 +83,17 @@
driftnet.1: driftnet.1.in Makefile
( echo '.\" DO NOT EDIT THIS FILE-- edit driftnet.1.in instead' ; sed s/@@@VERSION@@@/$(VERSION)/ ) < driftnet.1.in > driftnet.1

-endianness: endian
- ./endian > endianness
+endianness.h: endian
+ ./endian > endianness.h

endian: endian.c
$(CC) $(CFLAGS) -o endian endian.c

-%.o: %.c Makefile endianness
- $(CC) $(CFLAGS) `cat endianness` -c -o $@ $<
+%.o: %.c Makefile endianness.h
+ $(CC) $(CFLAGS) -c -o $@ $<

clean: nodepend
- rm -f *~ *.bak *.o core $(BINS) TAGS driftnet.1 endian endianness
+ rm -f *~ *.bak *.o core $(BINS) TAGS driftnet.1 endian endianness.h

tags:
etags *.c *.h
@@ -102,7 +105,7 @@
rm -rf driftnet-$(VERSION)
mv driftnet-$(VERSION).tar.gz ..

-depend: endianness
+depend: endianness.h
makedepend -- $(CFLAGS) `cat endianness` -- $(SRCS)
touch depend
rm -f Makefile.bak
diff -Naur driftnet-0.1.6/README driftnet/README
--- driftnet-0.1.6/README Tue Jul 9 12:26:41 2002
+++ driftnet/README Tue Aug 12 07:03:24 2003
@@ -1,5 +1,5 @@
README for driftnet
-$Id: README,v 1.7 2002/06/10 21:25:48 chris Exp $
+$Id: README,v 1.9 2003/08/12 14:03:24 chris Exp $

Driftnet watches network traffic, and picks out and displays JPEG and GIF
images for display. It is an horrific invasion of privacy and shouldn't be used
@@ -20,6 +20,18 @@

Driftnet needs to run with sufficient privilege to obtain raw packets from the
network. On most systems, this means running it as root.
+
+
+You can use Driftnet to sniff images passing over a wireless network. However,
+Driftnet does not understand the optional WEP encryption used with wireless
+ethernet. Instead, you can use Kismet, from
+ http://www.kismetwireless.net/
+to decrypt packets and pass them into a named pipe; the -f option can then be
+used to have Driftnet read the packets from the pipe. Thanks to Rob Timko and
+Joshua Wright for pointing this out; Rob's page,
+ http://68.38.68.127:81/writings/driftnet.html
+describes the process in greater detail.
+

If you find this program entertaining, you might want to help me develop it.
The TODO file contains a list of yet-to-be-done ideas.
diff -Naur driftnet-0.1.6/TODO driftnet/TODO
--- driftnet-0.1.6/TODO Tue Jul 9 12:26:41 2002
+++ driftnet/TODO Tue Aug 12 07:13:14 2003
@@ -1,5 +1,5 @@
TODO for driftnet
-$Id: TODO,v 1.10 2002/06/04 20:16:35 chris Exp $
+$Id: TODO,v 1.12 2003/08/12 14:13:14 chris Exp $

* PNG files.

@@ -23,4 +23,8 @@
* Safe(r) setuid operation.

* Drop privileges after starting up pcap.
+
+* PID file?
+
+* Delay between reading packets from dump file?

diff -Naur driftnet-0.1.6/connection.c driftnet/connection.c
--- driftnet-0.1.6/connection.c Tue Jul 9 12:26:41 2002
+++ driftnet/connection.c Thu Oct 16 04:56:37 2003
@@ -1,12 +1,15 @@
/*
* connection.c:
+ * Connection objects.
*
* Copyright (c) 2002 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
*/

-static const char rcsid[] = "$Id: connection.c,v 1.3 2002/07/08 23:32:33 chris Exp $";
+static const char rcsid[] = "$Id: connection.c,v 1.7 2003/10/16 11:56:37 chris Exp $";
+
+#include

#include
#include
@@ -16,52 +19,58 @@

#include "driftnet.h"

-/* connection_new:
- * Allocate a new connection structure between the given addresses. */
+/* connection_new SOURCE DEST SPORT DPORT
+ * Allocate a new connection structure for data sent from SOURCE:SPORT to
+ * DEST:DPORT. */
connection connection_new(const struct in_addr *src, const struct in_addr *dst, const short int sport, const short int dport) {
- connection c = (connection)calloc(1, sizeof(struct _connection));
+ connection c;
+ alloc_struct(_connection, c);
c->src = *src;
c->dst = *dst;
c->sport = sport;
c->dport = dport;
c->alloc = 16384;
- c->data = c->gif = c->jpeg = c->mpeg = malloc(c->alloc);
+ c->data = xmalloc(c->alloc);
c->last = time(NULL);
c->blocks = NULL;
return c;
}

-/* connection_delete:
- * Free the named connection structure. */
+/* connection_delete CONNECTION
+ * Free CONNECTION. */
void connection_delete(connection c) {
+ struct datablock *b;
+ for (b = c->blocks; b;) {
+ struct datablock *b2;
+ b2 = b->next;
+ free(b);
+ b = b2;
+ }
free(c->data);
free(c);
}

-/* connection_push:
- * Put some more data in a connection. */
+/* connection_push CONNECTION DATA OFFSET LENGTH
+ * Add LENGTH bytes of DATA received at OFFSET in the stream to CONNECTION. */
void connection_push(connection c, const unsigned char *data, unsigned int off, unsigned int len) {
- size_t goff = c->gif - c->data, joff = c->jpeg - c->data, moff = c->mpeg - c->data;
struct datablock *B, *b, *bl, BZ = {0};
int a;

assert(c->alloc > 0);
if (off + len > c->alloc) {
/* Allocate more memory. */
- while (off + len > c->alloc) {
+ do
c->alloc *= 2;
- c->data = (unsigned char*)realloc(c->data, c->alloc);
- }
+ while (off + len > c->alloc);
+ c->data = (unsigned char*)xrealloc(c->data, c->alloc);
}
- c->gif = c->data + goff;
- c->jpeg = c->data + joff;
- c->mpeg = c->data + moff;
+
memcpy(c->data + off, data, len);

if (off + len > c->len) c->len = off + len;
c->last = time(NULL);

- B = malloc(sizeof *B);
+ B = xmalloc(sizeof *B);
*B = BZ;
B->off = off;
B->len = len;
@@ -95,13 +104,5 @@
}
}
} while (a);
-/*
- {
- printf("%p: ", c);
- for (b = c->blocks; b; b = b->next)
- printf("[%d (%d) -> %d] ", b->off, b->len, b->off + b->len);
- printf("\n");
- }
-*/
}

diff -Naur driftnet-0.1.6/display.c driftnet/display.c
--- driftnet-0.1.6/display.c Tue Jul 9 12:26:41 2002
+++ driftnet/display.c Mon Apr 26 07:42:36 2004
@@ -9,17 +9,21 @@

#ifndef NO_DISPLAY_WINDOW

-static const char rcsid[] = "$Id: display.c,v 1.15 2002/06/13 20:06:42 chris Exp $";
+static const char rcsid[] = "$Id: display.c,v 1.19 2004/04/26 14:42:36 chris Exp $";

-#include
-#include
-#include
+#include
+
+#include
+#include
#include
#include
-#include
-#include
#include
-#include
+#include
+#include
+
+#include
+#include
+#include

#include

@@ -29,7 +33,7 @@
/* The border, in pixels, around images displayed in the window. */
#define BORDER 6

-extern int verbose; /* in driftnet.c */
+extern int verbose, beep; /* in driftnet.c */

static GtkWidget *window, *darea;
static GdkWindow *drawable;
@@ -80,7 +84,7 @@
/* Possible it has scrolled off the window. */
if (ir->x > width || ir->y + ir->h < 0) {
unlink(ir->filename);
- free(ir->filename);
+ xfree(ir->filename);
memset(ir, 0, sizeof *ir);
}
}
@@ -104,7 +108,7 @@
GdkGC *gc;
gc = gdk_gc_new(drawable);
gdk_draw_rgb_32_image(drawable, gc, 0, 0, width, height, GDK_RGB_DITHER_NORMAL, (guchar*)backing_image->flat, sizeof(pel) * width);
- gdk_gc_destroy(gc);
+ g_object_unref(gc);
}
}

@@ -128,7 +132,7 @@
/* scrolled off bottom, no longer in use. */
if ((ir->y + ir->h) < 0) {
unlink(ir->filename);
- free(ir->filename);
+ xfree(ir->filename);
memset(ir, 0, sizeof *ir);
}
}
@@ -145,7 +149,7 @@
break;
}
if (ir == imgrects + nimgrects) {
- imgrects = realloc(imgrects, 2 * nimgrects * sizeof *imgrects);
+ imgrects = xrealloc(imgrects, 2 * nimgrects * sizeof *imgrects);
memset(imgrects + nimgrects, 0, nimgrects * sizeof *imgrects);
ir = imgrects + nimgrects;
nimgrects *= 2;
@@ -172,7 +176,7 @@
* React to an expose event, perhaps changing the backing image size. */
void expose_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
if (darea) drawable = darea->window;
- gdk_window_get_size(drawable, &width, &height);
+ gdk_drawable_get_size(GDK_DRAWABLE(drawable), &width, &height);
if (!backing_image || backing_image->width != width || backing_image->height != height)
make_backing_image();

@@ -183,7 +187,7 @@
* React to a configure event, perhaps changing the backing image size. */
void configure_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
if (darea) drawable = darea->window;
- gdk_window_get_size(drawable, &width, &height);
+ gdk_drawable_get_size(GDK_DRAWABLE(drawable), &width, &height);
if (!backing_image || backing_image->width != width || backing_image->height != height)
make_backing_image();

@@ -205,7 +209,7 @@
struct stat st;

if (!name)
- name = calloc(strlen(savedimgpfx) + 16, 1);
+ name = xcalloc(strlen(savedimgpfx) + 16, 1);

do
sprintf(name, "%s%d%s", savedimgpfx, num++, strrchr(ir->filename, '.'));
@@ -301,10 +305,10 @@
int nimgs = 0;

if (!path)
- path = malloc(strlen(tmpdir) + 34);
+ path = xmalloc(strlen(tmpdir) + 34);

- /* We are sent messages continaing the length of the filename, then the
- * length of the file, then the filename. */
+ /* We are sent messages of size TMPNAMELEN containing a null-terminated
+ * file name. */
while (nimgs < 4 && (rr = xread(dpychld_fd, name, sizeof name)) == sizeof name) {
int saveimg = 0;
struct stat st;
@@ -319,7 +323,7 @@
if (verbose)
fprintf(stderr, PROGNAME": received image %s of size %d\n", name, (int)st.st_size);
/* Check to see whether this looks like an image we're interested in. */
- if (st.st_size > 256) {
+ if (st.st_size > 100) {
/* Small images are probably bollocks. */
img i = img_new();
if (!img_load_file(i, path, header, unknown))
@@ -350,6 +354,9 @@
add_image_rectangle(path, wrx, wry - h, w, h);
saveimg = 1;

+ if (beep)
+ write(1, "\a", 1);
+
update_window();

wrx += w + BORDER;
@@ -383,32 +390,30 @@
fcntl(dpychld_fd, F_SETFL, O_NONBLOCK);

/* set up list of image rectangles. */
- imgrects = calloc(nimgrects = 16, sizeof *imgrects);
+ imgrects = xcalloc(nimgrects = 16, sizeof *imgrects);

/* do some init thing */
gtk_init(&argc, &argv);
- gdk_rgb_init();

- gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
- gtk_widget_set_default_visual(gdk_rgb_get_visual());
+ gtk_widget_push_colormap(gdk_rgb_get_colormap());

/* Make our own window. */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_usize(window, 0, 0);
+ gtk_widget_set_size_request(window, 100, 100);

darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_set_events(darea, GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);

- gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
- gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);
+ g_signal_connect(G_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
+ g_signal_connect(G_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);

- gtk_signal_connect(GTK_OBJECT(darea), "expose-event", GTK_SIGNAL_FUNC(expose_event), NULL);
- gtk_signal_connect(GTK_OBJECT(darea), "configure_event", GTK_SIGNAL_FUNC(expose_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "expose-event", GTK_SIGNAL_FUNC(expose_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "configure_event", GTK_SIGNAL_FUNC(expose_event), NULL);

/* mouse button press/release for saving images */
- gtk_signal_connect(GTK_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_press_event), NULL);
- gtk_signal_connect(GTK_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_release_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_press_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_release_event), NULL);

gtk_widget_show_all(window);

@@ -419,7 +424,11 @@
if (ir->filename)
unlink(ir->filename);

- return 0;
+ img_delete(backing_image);
+
+ gtk_exit(0);
+
+ return 0; /* NOTREACHED */
}

#endif /* !NO_DISPLAY_WINDOW */
diff -Naur driftnet-0.1.6/driftnet.1.in driftnet/driftnet.1.in
--- driftnet-0.1.6/driftnet.1.in Tue Jul 9 12:26:41 2002
+++ driftnet/driftnet.1.in Mon Apr 26 07:42:36 2004
@@ -6,7 +6,7 @@
.\" Copyright (c) 2002 Chris Lightfoot. All rights reserved.
.\" Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
.\"
-.\" $Id: driftnet.1.in,v 1.5 2002/06/04 15:39:54 chris Exp $
+.\" $Id: driftnet.1.in,v 1.7 2004/04/26 14:42:36 chris Exp $
.\"

.SH NAME
@@ -37,6 +37,9 @@
\fB-v\fP
Print additional details of packets captured to the terminal.
.TP
+\fB-b\fP
+Beep when a new image is displayed.
+.TP
\fB-i\fP \fIinterface\fP
Listen to packets on \fIinterface\fP. By default, \fBdriftnet\fP will try to
pick up traffic on all interfaces, but this does not work with all versions of
@@ -101,7 +104,7 @@
.SH VERSION
\fBDriftnet\fP, version @@@VERSION@@@.
.br
-$Id: driftnet.1.in,v 1.5 2002/06/04 15:39:54 chris Exp $
+$Id: driftnet.1.in,v 1.7 2004/04/26 14:42:36 chris Exp $

.SH COPYING
This program is free software; you can redistribute it and/or modify
diff -Naur driftnet-0.1.6/driftnet.c driftnet/driftnet.c
--- driftnet-0.1.6/driftnet.c Tue Jul 9 12:26:41 2002
+++ driftnet/driftnet.c Thu Oct 16 04:56:37 2003
@@ -7,7 +7,7 @@
*
*/

-static const char rcsid[] = "$Id: driftnet.c,v 1.25 2002/07/08 20:57:17 chris Exp $";
+static const char rcsid[] = "$Id: driftnet.c,v 1.32 2003/10/16 11:56:37 chris Exp $";

#undef NDEBUG

@@ -45,9 +45,10 @@
connection *slots;
unsigned int slotsused, slotsalloc;

-/* flags: verbose, adjunct mode, temporary directory to use, media types to extract. */
+/* flags: verbose, adjunct mode, temporary directory to use, media types to
+ * extract, beep on image. */
int extract_images = 1;
-int verbose, adjunct;
+int verbose, adjunct, beep;
int tmpdir_specified;
char *tmpdir;
int max_tmpfiles;
@@ -85,14 +86,14 @@
char *buf;
size_t buflen;

- buf = malloc(buflen = strlen(tmpdir) + 64);
+ buf = xmalloc(buflen = strlen(tmpdir) + 64);

while ((de = readdir(d))) {
char *p;
p = strrchr(de->d_name, '.');
if (!tmpdir_specified || (p && strncmp(de->d_name, "driftnet-", 9) == 0 && (strcmp(p, ".jpeg") == 0 || strcmp(p, ".gif") == 0 || strcmp(p, ".mp3") == 0))) {
if (buflen < strlen(tmpdir) + strlen(de->d_name) + 1)
- buf = realloc(buf, buflen = strlen(tmpdir) + strlen(de->d_name) + 64);
+ buf = xrealloc(buf, buflen = strlen(tmpdir) + strlen(de->d_name) + 64);

sprintf(buf, "%s/%s", tmpdir, de->d_name);
unlink(buf);
@@ -100,7 +101,7 @@
}
closedir(d);

- free(buf);
+ xfree(buf);
}


@@ -116,7 +117,7 @@
if (!*C) return C;
}
/* No connection slots left. */
- slots = (connection*)realloc(slots, slotsalloc * 2 * sizeof(connection));
+ slots = (connection*)xrealloc(slots, slotsalloc * 2 * sizeof(connection));
memset(slots + slotsalloc, 0, slotsalloc * sizeof(connection));
C = slots + slotsalloc;
slotsalloc *= 2;
@@ -141,6 +142,7 @@
/* sweep_connections:
* Free finished connection slots. */
#define TIMEOUT 5
+#define MAXCONNECTIONDATA (8 * 1024 * 1024)

void sweep_connections(void) {
time_t now;
@@ -151,8 +153,11 @@
connection c = *C;
/* We discard connections which have seen no activity for TIMEOUT
* or for which a FIN has been seen and for which there are no
- * gaps in the stream. */
- if ((now - c->last) > TIMEOUT || (c->fin && (!c->blocks || !c->blocks->next))) {
+ * gaps in the stream, or where more than MAXCONNECTIONDATA have
+ * been captured. */
+ if ((now - c->last) > TIMEOUT
+ || (c->fin && (!c->blocks || !c->blocks->next))
+ || c->len > MAXCONNECTIONDATA) {
connection_extract_media(c, extract_type);
connection_delete(c);
*C = NULL;
@@ -212,10 +217,17 @@

case DLT_IEEE802:
return 22;
-
+
+#ifdef DLT_ATM_RFC1483
case DLT_ATM_RFC1483:
return 8;
+#endif

+#ifdef DLT_PRISM_HEADER
+ case DLT_PRISM_HEADER:
+ return 32;
+#endif
+
case DLT_RAW:
return 0;

@@ -229,6 +241,11 @@
return 16;
#endif

+#ifdef DLT_IEEE802_11 /* 802.11 wireless ethernet */
+ case DLT_IEEE802_11:
+ return 32; /* 20030606 email from Nikhil Bobb */ /*44; */
+#endif
+
default:;
}
fprintf(stderr, PROGNAME": unknown data link type %d", type);
@@ -254,8 +271,12 @@
"\n"
" -h Display this help message.\n"
" -v Verbose operation.\n"
+" -b Beep when a new image is captured.\n"
" -i interface Select the interface on which to listen (default: all\n"
" interfaces).\n"
+" -f file Instead of listening on an interface, read captured\n"
+" packets from a pcap dump file; file can be a named pipe\n"
+" for use with Kismet or similar.\n"
" -p Do not put the listening interface into promiscuous mode.\n"" -a Adjunct mode: do not display images on screen, but save\n"
" them to a temporary directory and announce their names on\n"
" standard output.\n"
@@ -294,9 +315,7 @@
}

/* terminate_on_signal:
- * Terminate on receipt of an appropriate signal. This is really ugly, because
- * the pcap_next call in the main loop may block, so it's best to just exit
- * here. */
+ * Terminate on receipt of an appropriate signal. */
sig_atomic_t foad;

void terminate_on_signal(int s) {
@@ -458,7 +477,7 @@
/* main:
* Entry point. Process command line options, start up pcap and enter capture
* loop. */
-char optstring[] = "hi:psSMvam:d:x:";
+char optstring[] = "abd:f:hi:M:m:pSsvx:";

int main(int argc, char *argv[]) {
char *interface = NULL, *filterexpr;
@@ -472,7 +491,10 @@
extern char *audio_mpeg_player; /* in playaudio.c */
int newpfx = 0;
int mpeg_player_specified = 0;
+ char *dumpfile = NULL;
+
pthread_t packetth;
+ connection *C;

/* Handle command-line options. */
opterr = 0;
@@ -483,6 +505,10 @@
return 0;

case 'i':
+ if (dumpfile) {
+ fprintf(stderr, PROGNAME": can't specify -i and -f\n");
+ return -1;
+ }
interface = optarg;
break;

@@ -490,6 +516,13 @@
verbose = 1;
break;

+ case 'b':
+ if (!isatty(1))
+ fprintf(stderr, PROGNAME": can't beep unless standard output is a terminal\n");
+ else
+ beep = 1;
+ break;
+
case 'p':
promisc = 0;
break;
@@ -524,6 +557,14 @@
tmpdir_specified = 1; /* so we don't delete it. */
break;

+ case 'f':
+ if (interface) {
+ fprintf(stderr, PROGNAME": can't specify -i and -f\n");
+ return -1;
+ }
+ dumpfile = optarg;
+ break;
+
#ifndef NO_DISPLAY_WINDOW
case 'x':
savedimgpfx = optarg;
@@ -568,6 +609,15 @@
if (max_tmpfiles && adjunct && verbose)
fprintf(stderr, PROGNAME": a maximum of %d images will be buffered\n", max_tmpfiles);

+ if (beep && adjunct)
+ fprintf(stderr, PROGNAME": can't beep in adjunct mode\n");
+
+ /* In adjunct mode, it's important that the attached program gets
+ * notification of images in a timely manner. Make stdout line-buffered
+ * for this reason. */
+ if (adjunct)
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
/* If a directory name has not been specified, then we need to create one.
* Otherwise, check that it's a directory into which we may write files. */
if (tmpdir) {
@@ -585,10 +635,10 @@
} else {
/* need to make a temporary directory. */
for (;;) {
- tmpdir = strdup(tmpnam(NULL));
+ tmpdir = strdup(tmpnam(NULL)); /* may generate a warning, but this is safe because we create a directory not a file */
if (mkdir(tmpdir, 0700) == 0)
break;
- free(tmpdir);
+ xfree(tmpdir);
}
}

@@ -606,16 +656,20 @@

/* Build up filter. */
if (optind < argc) {
- char **a;
- int l;
- for (a = argv + optind, l = sizeof("tcp and ()"); *a; l += strlen(*a) + 1, ++a);
- filterexpr = calloc(l, 1);
- strcpy(filterexpr, "tcp and (");
- for (a = argv + optind; *a; ++a) {
- strcat(filterexpr, *a);
- if (*(a + 1)) strcat(filterexpr, " ");
+ if (dumpfile)
+ fprintf(stderr, PROGNAME": filter code ignored with dump file\n");
+ else {
+ char **a;
+ int l;
+ for (a = argv + optind, l = sizeof("tcp and ()"); *a; l += strlen(*a) + 1, ++a);
+ filterexpr = calloc(l, 1);
+ strcpy(filterexpr, "tcp and (");
+ for (a = argv + optind; *a; ++a) {
+ strcat(filterexpr, *a);
+ if (*(a + 1)) strcat(filterexpr, " ");
+ }
+ strcat(filterexpr, ")");
}
- strcat(filterexpr, ")");
} else filterexpr = "tcp";

if (verbose)
@@ -662,27 +716,33 @@
#endif /* !NO_DISPLAY_WINDOW */

/* Start up pcap. */
+ if (dumpfile) {
+ if (!(pc = pcap_open_offline(dumpfile, ebuf))) {
+ fprintf(stderr, PROGNAME": pcap_open_offline: %s\n", ebuf);
+ return -1;
+ }
+ } else {
+ if (!(pc = pcap_open_live(interface, SNAPLEN, promisc, 1000, ebuf))) {
+ fprintf(stderr, PROGNAME": pcap_open_live: %s\n", ebuf);

- pc = pcap_open_live(interface, SNAPLEN, promisc, 1000, ebuf);
- if (!pc) {
- fprintf(stderr, PROGNAME": pcap_open_live: %s\n", ebuf);
-
- if (getuid() != 0)
- fprintf(stderr, PROGNAME": perhaps you need to be root?\n");
- else if (!interface)
- fprintf(stderr, PROGNAME": perhaps try selecting an interface with the -i option?\n");
-
- return -1;
- }
-
- if (pcap_compile(pc, &filter, (char*)filterexpr, 1, 0) == -1) {
- fprintf(stderr, PROGNAME": pcap_compile: %s\n", pcap_geterr(pc));
- return -1;
- }
+ if (getuid() != 0)
+ fprintf(stderr, PROGNAME": perhaps you need to be root?\n");
+ else if (!interface)
+ fprintf(stderr, PROGNAME": perhaps try selecting an interface with the -i option?\n");
+
+ return -1;
+ }

- if (pcap_setfilter(pc, &filter) == -1) {
- fprintf(stderr, PROGNAME": pcap_setfilter: %s\n", pcap_geterr(pc));
- return -1;
+ /* Only apply a filter to live packets. Is this right? */
+ if (pcap_compile(pc, &filter, (char*)filterexpr, 1, 0) == -1) {
+ fprintf(stderr, PROGNAME": pcap_compile: %s\n", pcap_geterr(pc));
+ return -1;
+ }
+
+ if (pcap_setfilter(pc, &filter) == -1) {
+ fprintf(stderr, PROGNAME": pcap_setfilter: %s\n", pcap_geterr(pc));
+ return -1;
+ }
}

/* Figure out the offset from the start of a returned packet to the data in
@@ -693,7 +753,7 @@

slotsused = 0;
slotsalloc = 64;
- slots = (connection*)calloc(slotsalloc, sizeof(connection));
+ slots = (connection*)xcalloc(slotsalloc, sizeof(connection));

/* Actually start the capture stuff up. Unfortunately, on many platforms,
* libpcap doesn't have read timeouts, so we start the thing up in a
@@ -724,8 +784,15 @@
pthread_join(packetth, NULL);

/* Clean up. */
+/* pcap_freecode(pc, &filter);*/ /* not on some systems... */
pcap_close(pc);
clean_temporary_directory();
+
+ /* Easier for memory-leak debugging if we deallocate all this here.... */
+ for (C = slots; C < slots + slotsalloc; ++C)
+ if (*C) connection_delete(*C);
+ xfree(slots);
+ xfree(tmpdir);

return 0;
}
diff -Naur driftnet-0.1.6/driftnet.h driftnet/driftnet.h
--- driftnet-0.1.6/driftnet.h Mon Aug 23 22:40:05 2004
+++ driftnet/driftnet.h Thu Apr 8 16:06:29 2004
@@ -5,7 +5,7 @@
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
- * $Id: driftnet.h,v 1.9 2002/06/13 20:06:42 chris Exp $
+ * $Id: driftnet.h,v 1.13 2004/04/08 23:06:29 chris Exp $
*
*/

@@ -14,18 +14,27 @@

#define PROGNAME "driftnet"

-#include /* added 20020604 edobbs for OpenBSD */
+#include
+
#include
#include
#include
#include
#include
+#ifndef USE_SYS_TYPES_H
+# include
+#endif
+
+/* alloc_struct S P
+ * Make P point to a new struct S, initialised as if in static storage (like
+ * = {0}). */
+#define alloc_struct(S, p) do { struct S as__z = {0}; p = xmalloc(sizeof *p); *p = as__z; } while (0)

/* enum mediatype:
- * Characterise types of media which we can extract. */
-enum mediatype { m_image = 1, m_audio = 2 };
+ * Bit field to characterise types of media which we can extract. */
+enum mediatype { m_image = 1, m_audio = 2, m_text = 4 };

-#define NMEDIATYPES 3 /* keep up to date with media.c */
+#define NMEDIATYPES 5 /* keep up to date with media.c */

/* struct datablock:
* Represents an extent in a captured stream. */
@@ -35,15 +44,27 @@
};

/* connection:
- * Object representing one half of a TCP stream connection. */
+ * Object representing one half of a TCP stream connection. Each connection
+ * maintains a record of the data which has been recovered from the network
+ * and a list of blocks of data which represent valid data in the buffer, so
+ * that if there is a gap in the received data, we don't search it for
+ * data. */
typedef struct _connection {
+ /* Source/destination address/port of this half-duplex connection. */
struct in_addr src, dst;
short int sport, dport;
+ /* The TCP initial-sequence-number of the connection. */
uint32_t isn;
- unsigned int len, off, alloc;
- unsigned char *data, *gif, *jpeg, *mpeg;
+ /* The highest offset and the buffer size allocated, and the buffer
+ * itself. */
+ unsigned int len, alloc;
+ unsigned char *data;
+ /* Flag indicating that we've seen a FIN-flagged segment for this stream,
+ * so that it is undergoing a shutdown. */
int fin;
+ /* The time at which we last received any data on this stream. */
time_t last;
+ /* A list of the extents in the buffer which contain valid data. */
struct datablock *blocks;
} *connection;

@@ -60,6 +81,14 @@

/* media.c */
void connection_extract_media(connection c, const enum mediatype T);
+
+/* util.c */
+void *xmalloc(size_t n);
+void *xcalloc(size_t n, size_t m);
+void *xrealloc(void *w, size_t n);
+void xfree(void *v);
+char *xstrdup(const char *s);
+unsigned char *memstr(const unsigned char *haystack, const size_t hlen, const unsigned char *needle, const size_t nlen);

#define TMPNAMELEN 64

diff -Naur driftnet-0.1.6/endian.c driftnet/endian.c
--- driftnet-0.1.6/endian.c Tue Jul 9 12:26:41 2002
+++ driftnet/endian.c Mon Nov 3 02:40:23 2003
@@ -7,7 +7,7 @@
*
*/

-static const char rcsid[] = "$Id: endian.c,v 1.5 2002/06/10 21:25:48 chris Exp $";
+static const char rcsid[] = "$Id: endian.c,v 1.6 2003/11/03 10:40:23 chris Exp $";

#include
#ifdef USE_SYS_TYPES_H
@@ -18,18 +18,18 @@

int main(void) {
#if defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)
- printf("-DDRIFTNET_LITTLE_ENDIAN\n");
+ printf("#define DRIFTNET_LITTLE_ENDIAN\n");
return 0;
#elif defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)
- printf("-DDRIFTNET_BIG_ENDIAN\n");
+ printf("#define DRIFTNET_BIG_ENDIAN\n");
return 0;
#else
uint32_t a = 0;
*((uint8_t*)&a) = 0xff;
if (a == 0xff000000)
- printf("-DDRIFTNET_BIG_ENDIAN\n");
+ printf("#define DRIFTNET_BIG_ENDIAN\n");
else if (a == 0x000000ff)
- printf("-DDRIFTNET_LITTLE_ENDIAN\n");
+ printf("#define DRIFTNET_LITTLE_ENDIAN\n");
else
return -1; /* don't know. */
#endif /* endianness test */
diff -Naur driftnet-0.1.6/http.c driftnet/http.c
--- driftnet-0.1.6/http.c Wed Dec 31 16:00:00 1969
+++ driftnet/http.c Tue Aug 12 07:14:15 2003
@@ -0,0 +1,124 @@
+/*
+ * http.c:
+ * Look for HTTP requests in buffers.
+ *
+ * We look for GET requests only, and only if the response is of type
+ * text/html.
+ *
+ * Copyright (c) 2003 Chris Lightfoot. All rights reserved.
+ * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
+ *
+ */
+
+static const char rcsid[] = "$Id: http.c,v 1.1 2003/08/12 14:14:15 chris Exp $";
+
+#include
+
+#include
+#include
+
+#include "driftnet.h"
+
+/* find_http_req DATA LEN FOUND FOUNDLEN
+ * Look for an HTTP request and response in buffer DATA of length LEN. The
+ * return value is a pointer into DATA suitable for a subsequent call to this
+ * function; *FOUND is either NULL, or a pointer to the start of an HTTP
+ * request; in the latter case, *FOUNDLEN is the length of the match
+ * containing enough information to obtain the URL. */
+unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen) {
+ unsigned char *req, *le, *blankline, *hosthdr;
+
+#define remaining(x) (len - (data - (x)))
+#define MAX_REQ 16384
+
+ /* HTTP requests look like:
+ *
+ * GET {path} HTTP/1.(0|1)\r\n
+ * header: value\r\n
+ * ...
+ * \r\n
+ *
+ * We may care about the Host: header in the request. */
+ if (len < 40)
+ return (unsigned char*)data;
+
+ if (!(req = memstr(data, len, "GET ", 4)))
+ return (unsigned char*)(data + len - 4);
+
+ /* Find the end of the request line. */
+ if (!(le = memstr(req + 4, remaining(req + 4), "\r\n", 2))) {
+ if (remaining(req + 4) > MAX_REQ)
+ return (unsigned char*)(req + 4);
+ else
+ return (unsigned char*)req;
+ }
+
+ /* Not enough space for a path. */
+ if (le < req + 5)
+ return le + 2;
+
+ /* Not an HTTP request, just a line starting GET.... */
+ if (memcmp(le - 9, " HTTP/1.", 8) || !strchr("01", (int)*(le - 1)))
+ return le + 2;
+
+ /* Find the end of the request headers. */
+ if (!(blankline = memstr(le + 2, remaining(le + 2), "\r\n\r\n", 4))) {
+ if (remaining(le + 2) > MAX_REQ)
+ return (unsigned char*)(data + len - 4);
+ else
+ return req;
+ }
+
+ if (memcmp(req + 4, "http://", 7) == 0)
+ /* Probably a cache request; in any case, don't need to look for a Host:. */
+ goto found;
+
+ /* Is there a Host: header? */
+ if (!(hosthdr = memstr(le, blankline - le + 2, "\r\nHost: ", 8))) {
+ return blankline + 4;
+ }
+
+found:
+
+ *http = req;
+ *httplen = blankline - req;
+
+ return blankline + 4;
+}
+
+void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len) {
+ char *url;
+ const char *path, *host;
+ int pathlen, hostlen;
+ const unsigned char *p;
+
+ if (!(p = memstr(data, len, "\r\n", 2)))
+ return;
+
+ path = (const char*)(data + 4);
+ pathlen = (p - 9) - (unsigned char*)path;
+
+ if (memcmp(path, "http://", 7) == 0) {
+ url = malloc(pathlen + 1);
+ sprintf(url, "%.*s", pathlen, path);
+ } else {
+
+ if (!(p = memstr(p, len - (p - data), "\r\nHost: ", 8)))
+ return;
+
+ host = (const char*)(p + 8);
+
+ if (!(p = memstr(p + 8, len - (p + 8 - data), "\r\n", 2)))
+ return;
+ hostlen = p - (const unsigned char*)host;
+
+ if (hostlen == 0)
+ return;
+
+ url = malloc(hostlen + pathlen + 9);
+ sprintf(url, "http://%.*s%.*s", hostlen, host, pathlen, path);
+ }
+
+ fprintf(stderr, "\n\n %s\n\n", url);
+ free(url);
+}
diff -Naur driftnet-0.1.6/image.c driftnet/image.c
--- driftnet-0.1.6/image.c Tue Jul 9 12:26:41 2002
+++ driftnet/image.c Mon Aug 25 05:23:43 2003
@@ -7,40 +7,20 @@
*
*/

-static const char rcsid[] = "$Id: image.c,v 1.10 2002/07/02 22:17:25 chris Exp $";
+static const char rcsid[] = "$Id: image.c,v 1.13 2003/08/25 12:23:43 chris Exp $";

#include
#include
#include
+#include

-/* memstr:
- * Locate needle, of length n_len, in haystack, of length h_len, returning NULL.
- * Uses the Boyer-Moore search algorithm. Cf.
- * http://www-igm.univ-mlv.fr/~lecroq/string/node14.html */
-static unsigned char *memstr(const unsigned char *haystack, const size_t hlen,
- const unsigned char *needle, const size_t nlen) {
- int skip[256], k;
-
- if (nlen == 0) return (char*)haystack;
-
- /* Set up the finite state machine we use. */
- for (k = 0; k < 255; ++k) skip[k] = nlen;
- for (k = 0; k < nlen - 1; ++k) skip[needle[k]] = nlen - k - 1;
-
- /* Do the search. */
- for (k = nlen - 1; k < hlen; k += skip[haystack[k]]) {
- int i, j;
- for (j = nlen - 1, i = k; j >= 0 && haystack[i] == needle[j]; j--) i--;
- if (j == -1) return (unsigned char*)(haystack + i + 1);
- }
-
- return NULL;
-}
+#include "img.h"

+#include "driftnet.h"

/* If we run out of space, put us back to the last candidate GIF header. */
/*#define spaceleft do { if (block > data + len) { printf("ran out of space\n"); return gifhdr; } } while (0)*/
-#define spaceleft if (block > data + len) return gifhdr
+#define spaceleft if (block >= data + len) return gifhdr /* > ?? */

unsigned char *find_gif_image(const unsigned char *data, const size_t len, unsigned char **gifdata, size_t *giflen) {
unsigned char *gifhdr, *block;
@@ -59,6 +39,7 @@
ncolours = (1 << ((gifhdr[10] & 0x7) + 1));
/* printf("gif header %d colours\n", ncolours); */
block = gifhdr + 13;
+ spaceleft;
if (gifhdr[10] & 0x80) block += 3 * ncolours; /* global colour table */
spaceleft;

@@ -68,9 +49,12 @@
case 0x2c:
/* image block */
/* printf("image data\n"); */
- if (block[9] & 0x80)
+ if (block + 9 > data + len) return gifhdr;
+ if (block[9] & 0x80) {
/* local colour table */
block += 3 * ((1 << ((gifhdr[9] & 0x7) + 1)));
+ spaceleft;
+ }
block += 10;
++block; /* lzw code size */
do {
@@ -195,7 +179,7 @@
if (!block || (block - data) >= len) return jpeghdr;

/* now we need to find the onward count from this place */
- while ((block = jpeg_skip_block(block + 1, len - (block - data)))) {
+ while ((block = jpeg_skip_block(block + 1, len - (block + 1 - data)))) {
/* printf("data = %p block = %p\n", data, block); */

block = jpeg_next_marker(block, len - (block - data));
@@ -217,6 +201,64 @@
/* printf("nope, no complete JPEG here\n"); */
return jpeghdr;
}
+
+/* find_png_eoi BUFFER LEN
+ * Returns the first position in BUFFER of LEN bytes after the end of the image
+ * or NULL if end of image not found. */
+unsigned char *find_png_eoi(unsigned char *buffer, const size_t len) {
+ unsigned char *end_data, *data, chunk_code[PNG_CODE_LEN + 1];
+ struct png_chunk chunk;
+ u_int32_t datalen;
+
+ /* Move past the PNG header */
+ data = (buffer + PNG_SIG_LEN);
+ end_data = (buffer + len - (sizeof(struct png_chunk) + PNG_CRC_LEN));
+
+ while (data <= end_data) {
+ memcpy(&chunk, data, sizeof chunk);
+/* chunk = (struct png_chunk *)data; */ /* can't do that. */
+ memset(chunk_code, '\0', PNG_CODE_LEN + 1);
+ memcpy(chunk_code, chunk.code, PNG_CODE_LEN);
+
+ datalen = ntohl(chunk.datalen);
+
+ if (!strncasecmp(chunk_code, "iend", PNG_CODE_LEN))
+ return (unsigned char *)(data + sizeof(struct png_chunk) + PNG_CRC_LEN);
+
+ /* Would this push us off the end of the buffer? */
+ if (datalen > (len - (data - buffer)))
+ return NULL;
+
+ data += (sizeof(struct png_chunk) + datalen + PNG_CRC_LEN);
+ }
+
+ return NULL;
+}
+
+/* find_png_image DATA LEN PNGDATA PNGLEN
+ * Look for PNG images in LEN bytes buffer DATA. */
+unsigned char *find_png_image(const unsigned char *data, const size_t len, unsigned char **pngdata, size_t *pnglen) {
+ unsigned char *pnghdr, *data_end, *png_eoi;
+
+ *pngdata = NULL;
+
+ if (len < PNG_SIG_LEN)
+ return (unsigned char*)data;
+
+ pnghdr = memstr(data, len, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", PNG_SIG_LEN);
+ if (!pnghdr)
+ return (unsigned char*)(data + len - PNG_SIG_LEN);
+
+ data_end = (unsigned char *)(data + len);
+
+ if ((png_eoi = find_png_eoi(pnghdr, (data_end - pnghdr))) == NULL)
+ return pnghdr;
+
+ *pngdata = pnghdr;
+ *pnglen = (png_eoi - pnghdr);
+ return png_eoi;
+}
+

#if 0
#include
diff -Naur driftnet-0.1.6/img.c driftnet/img.c
--- driftnet-0.1.6/img.c Tue Jul 9 12:26:41 2002
+++ driftnet/img.c Mon Aug 25 05:23:43 2003
@@ -9,12 +9,13 @@

#ifndef NO_DISPLAY_WINDOW

-static const char rcsid[] = "$Id: img.c,v 1.9 2002/07/08 20:57:17 chris Exp $";
+static const char rcsid[] = "$Id: img.c,v 1.11 2003/08/25 12:23:43 chris Exp $";

#include
#include
#include

+#include "driftnet.h"
#include "img.h"

#define INLINE inline
@@ -38,6 +39,12 @@
int jpeg_load_img(img I);
int jpeg_save_img(const img I, FILE *fp);

+/* png.c */
+int png_load_hdr(img I);
+/*int png_abort_load(img I);*/
+int png_load_img(img I);
+/*int png_save_img(const img I, FILE *fp);*/
+
#if 0
/* raw.c */
int raw_load_img(img I);
@@ -59,8 +66,9 @@
*/
{gif, ".gif\0", gif_load_hdr, gif_abort_load, gif_load_img, NULL},
{jpeg, ".jpg\0.jpeg\0", jpeg_load_hdr, jpeg_abort_load, jpeg_load_img, jpeg_save_img},
+ {png, ".png\0", png_load_hdr, NULL /*png_abort_load*/,
+ png_load_img, NULL /*png_save_img*/},
/*
- {png, ".png\0", png_load_hdr, png_abort_load, png_load_img, png_save_img},
{raw, "", NULL, raw_load_img, NULL, raw_save_img},
*/
};
@@ -68,18 +76,16 @@
#define NUMFILEDRVS (sizeof(filedrvs) / sizeof(struct filedrv))

/* img_new:
- * Create a new empty image object.
- */
+ * Create a new empty image object. */
img img_new(void) {
img I;
- I = (img)malloc(sizeof(struct _img));
+ I = (img)xmalloc(sizeof(struct _img));
memset(I, 0, sizeof(struct _img));
return I;
}

/* img_new_blank:
- * Create a new image object.
- */
+ * Create a new image object. */
img img_new_blank(const unsigned int width, const unsigned int height) {
img I = img_new();
I->width = width;
@@ -91,28 +97,26 @@

/* img_alloc:
* Allocate memory for an image object. The memory is allocated as a big
- * block, with pointers fixed up at the beginning.
- */
+ * block, with pointers fixed up at the beginning. */
void img_alloc(img I) {
pel **p, *q;
- I->data = (pel**)calloc(I->height * sizeof(pel*) + I->width * I->height * sizeof(pel), 1);
+ I->data = (pel**)xcalloc(I->height * sizeof(pel*) + I->width * I->height * sizeof(pel), 1);
I->flat = (pel*)(I->data + I->height);
for (p = I->data, q = I->flat; p < I->data + I->height; ++p, q += I->width)
*p = q;
}

/* img_delete:
- * Free memory associated with an image object.
- */
+ * Free memory associated with an image object. */
void img_delete(img I) {
- if (I->data) free(I->data);
- free(I);
+ if (I->data) xfree(I->data);
+ if (I->fp) fclose(I->fp);
+ xfree(I);
}

/* img_load:
* Load an image, or part of it, from the associated stream. Returns 1 on
- * success or 0 on failure.
- */
+ * success or 0 on failure. */
int img_load(img I, const imgstate howmuch, const imgtype type) {
int i;
if (type == unknown) {
@@ -145,16 +149,14 @@
}

/* img_load_stream:
- * Associate an image with a stream and load something from it.
- */
+ * Associate an image with a stream and load something from it. */
int img_load_stream(img I, FILE *fp, const imgstate howmuch, const imgtype type) {
I->fp = fp;
return img_load(I, howmuch, type);
}

/* img_load_file:
- * Load an image, or part of it, from a file.
- */
+ * Load an image, or part of it, from a file. */
int img_load_file(img I, const char *name, const imgstate howmuch, const imgtype type) {
if (howmuch == none) return 1;
I->fp = fopen(name, "rb");
@@ -183,8 +185,7 @@
}

/* img_save_file:
- * Save an image in a file of the specified type.
- */
+ * Save an image in a file of the specified type. */
int img_save(const img I, FILE *fp, const imgtype type) {
int i;
if (type == unknown) {
@@ -201,8 +202,7 @@
/* img_clip_adj_x:
* img_clip_adj_y:
* Return an adjustment to the passed coordinate which will put it in the
- * clipping region for the image.
- */
+ * clipping region for the image. */
INLINE int img_clip_adj_x(const img I, const int x) {
if (x < 0) return -x;
if (x >= I->width) return I->width - x;
@@ -216,16 +216,14 @@
}

/* img_clip:
- * Clip coordinates against an image.
- */
+ * Clip coordinates against an image. */
INLINE void img_clip(const img I, int *x, int *y) {
*x += img_clip_adj_x(I, *x);
*y += img_clip_adj_y(I, *y);
}

/* img_simple_blt:
- * Copy a rectangle, ignoring clipping and overlapping regions.
- */
+ * Copy a rectangle, ignoring clipping and overlapping regions. */
INLINE void img_simple_blt(img dest, const int dx, const int dy, img src, const int sx, const int sy, const int w, const int h) {
int y, y2;
for (y = sy, y2 = dy; y < sy + h; ++y, ++y2)
diff -Naur driftnet-0.1.6/img.h driftnet/img.h
--- driftnet-0.1.6/img.h Tue Jul 9 12:26:41 2002
+++ driftnet/img.h Mon Nov 3 02:40:23 2003
@@ -5,7 +5,7 @@
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
- * $Id: img.h,v 1.7 2002/07/08 20:57:17 chris Exp $
+ * $Id: img.h,v 1.9 2003/11/03 10:40:23 chris Exp $
*
*/

@@ -22,6 +22,8 @@

#include

+#include "endianness.h"
+
typedef uint8_t chan;
typedef uint32_t pel;

@@ -46,6 +48,10 @@
# error "no endianness defined"
#endif

+#define PNG_CODE_LEN 4
+#define PNG_CRC_LEN 4
+#define PNG_SIG_LEN 8
+
typedef enum { unknown = 0, pnm = 1, gif = 2, jpeg = 3, png = 4, raw = 5 } imgtype;
typedef enum { none = 0, header = 1, full = 2 } imgstate;

@@ -67,6 +73,11 @@
void *us;
imgerr err;
} *img;
+
+struct png_chunk {
+ uint32_t datalen;
+ unsigned char code[PNG_CODE_LEN];
+};

img img_new(void);
img img_new_blank(const unsigned int width, const unsigned int height);
diff -Naur driftnet-0.1.6/jpeg.c driftnet/jpeg.c
--- driftnet-0.1.6/jpeg.c Tue Jul 9 12:26:41 2002
+++ driftnet/jpeg.c Tue Aug 12 07:09:57 2003
@@ -9,13 +9,14 @@

#ifndef NO_DISPLAY_WINDOW

-static const char rcsid[] = "$Id: jpeg.c,v 1.5 2002/07/08 20:57:17 chris Exp $";
+static const char rcsid[] = "$Id: jpeg.c,v 1.6 2003/08/12 14:09:57 chris Exp $";

#include
#include
#include
#include

+#include "driftnet.h"
#include "img.h"

/* struct my_error_mgr:
@@ -38,9 +39,9 @@
int jpeg_load_hdr(img I) {
struct jpeg_decompress_struct *cinfo;
struct my_error_mgr *jerr;
- cinfo = (struct jpeg_decompress_struct*)calloc(sizeof(struct jpeg_decompress_struct), 1);
+ alloc_struct(jpeg_decompress_struct, cinfo);
I->us = cinfo;
- jerr = (struct my_error_mgr*)calloc(sizeof(struct my_error_mgr), 1);
+ alloc_struct(my_error_mgr, jerr);
cinfo->err = jpeg_std_error(&jerr->pub);
jerr->pub.error_exit = my_error_exit;
if (setjmp(jerr->jb)) {
diff -Naur driftnet-0.1.6/media.c driftnet/media.c
--- driftnet-0.1.6/media.c Tue Jul 9 12:26:41 2002
+++ driftnet/media.c Mon Aug 25 05:23:43 2003
@@ -7,7 +7,7 @@
*
*/

-static const char rcsid[] = "$Id: media.c,v 1.6 2002/07/08 23:32:33 chris Exp $";
+static const char rcsid[] = "$Id: media.c,v 1.9 2003/08/25 12:23:43 chris Exp $";

#include
#include
@@ -27,10 +27,15 @@
/* image.c */
unsigned char *find_gif_image(const unsigned char *data, const size_t len, unsigned char **gifdata, size_t *giflen);
unsigned char *find_jpeg_image(const unsigned char *data, const size_t len, unsigned char **jpegdata, size_t *jpeglen);
+unsigned char *find_png_image(const unsigned char *data, const size_t len, unsigned char **pngdata, size_t *pnglen);

/* audio.c */
unsigned char *find_mpeg_stream(const unsigned char *data, const size_t len, unsigned char **mpegdata, size_t *mpeglen);

+/* http.c */
+unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen);
+void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len);
+
/* playaudio.c */
void mpeg_submit_chunk(const unsigned char *data, const size_t len);

@@ -49,7 +54,7 @@
while ((de = readdir(d))) {
char *p;
p = strrchr(de->d_name, '.');
- if (p && (strncmp(de->d_name, "driftnet-", 9) == 0 && (strcmp(p, ".jpeg") == 0 || strcmp(p, ".gif") == 0 || strcmp(p, ".mp3") == 0)))
+ if (p && (strncmp(de->d_name, "driftnet-", 9) == 0 && (strcmp(p, ".jpeg") == 0 || strcmp(p, ".gif") == 0 || strcmp(p, ".png") == 0 || strcmp(p, ".mp3") == 0)))
++num;
}
closedir(d);
@@ -62,13 +67,14 @@
/* dispatch_image:
* Throw some image data at the display process. */
void dispatch_image(const char *mname, const unsigned char *data, const size_t len) {
- char *buf, name[TMPNAMELEN];
+ char *buf, name[TMPNAMELEN] = {0};
int fd;
- buf = malloc(strlen(tmpdir) + 64);
+ buf = xmalloc(strlen(tmpdir) + 64);
sprintf(name, "driftnet-%08x%08x.%s", (unsigned int)time(NULL), rand(), mname);
sprintf(buf, "%s/%s", tmpdir, name);
fd = open(buf, O_WRONLY | O_CREAT | O_EXCL, 0644);
- if (fd == -1) return;
+ if (fd == -1)
+ return;
write(fd, data, len);
close(fd);

@@ -79,7 +85,7 @@
write(dpychld_fd, name, sizeof name);
#endif /* !NO_DISPLAY_WINDOW */

- free(buf);
+ xfree(buf);
}

/* dispatch_mpeg_audio:
@@ -98,11 +104,13 @@
} driver[NMEDIATYPES] = {
{ "gif", m_image, find_gif_image, dispatch_image },
{ "jpeg", m_image, find_jpeg_image, dispatch_image },
- { "mpeg", m_audio, find_mpeg_stream, dispatch_mpeg_audio }
+ { "png", m_image, find_png_image, dispatch_image },
+ { "mpeg", m_audio, find_mpeg_stream, dispatch_mpeg_audio },
+ { "HTTP", m_text, find_http_req, dispatch_http_req }
};

-/* connection_extract_media:
- * Attempt to extract media data of given type/s from the named connection. */
+/* connection_extract_media CONNECTION TYPE
+ * Attempt to extract media data of the given TYPE from CONNECTION. */
void connection_extract_media(connection c, const enum mediatype T) {
struct datablock *b;
extern int max_tmpfiles; /* in driftnet.c */
diff -Naur driftnet-0.1.6/mpeghdr.h driftnet/mpeghdr.h
--- driftnet-0.1.6/mpeghdr.h Tue Jul 9 12:26:41 2002
+++ driftnet/mpeghdr.h Tue May 20 09:49:08 2003
@@ -5,7 +5,7 @@
* Copyright (c) 2002 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
- * $Id: mpeghdr.h,v 1.3 2002/06/10 21:25:48 chris Exp $
+ * $Id: mpeghdr.h,v 1.4 2003/05/20 16:49:08 chris Exp $
*
*/

@@ -15,7 +15,7 @@
#ifdef USE_SYS_TYPES_H
# include /* Solaris etc. */
#else
-# include /* C99 standard. */
+# include /* C99 standard. */
#endif

#include
diff -Naur driftnet-0.1.6/playaudio.c driftnet/playaudio.c
--- driftnet-0.1.6/playaudio.c Tue Jul 9 12:26:41 2002
+++ driftnet/playaudio.c Tue Aug 12 07:12:29 2003
@@ -13,7 +13,7 @@
*
*/

-static const char rcsid[] = "$Id: playaudio.c,v 1.4 2002/06/04 19:09:02 chris Exp $";
+static const char rcsid[] = "$Id: playaudio.c,v 1.5 2003/08/12 14:12:29 chris Exp $";

#include

@@ -57,10 +57,10 @@
* Allocate a buffer and copy some data into it. */
static audiochunk audiochunk_new(const unsigned char *data, const size_t len) {
audiochunk A;
- A = calloc(1, sizeof *A);
+ alloc_struct(_audiochunk, A);
A->len = len;
if (data) {
- A->data = malloc(len);
+ A->data = xmalloc(len);
memcpy(A->data, data, len);
}
return A;
@@ -69,8 +69,8 @@
/* audiochunk_delete:
* Free memory from an audiochunk. */
static void audiochunk_delete(audiochunk A) {
- free(A->data);
- free(A);
+ xfree(A->data);
+ xfree(A);
}

/* audiochunk_write:
diff -Naur driftnet-0.1.6/png.c driftnet/png.c
--- driftnet-0.1.6/png.c Tue Jul 9 12:26:41 2002
+++ driftnet/png.c Mon Aug 25 05:23:43 2003
@@ -1,10 +1,161 @@
/*
* png.c:
+ * PNG image support.
*
- * Copyright (c) 2001 Chris Lightfoot. All rights reserved.
+ * Copyright (c) 2003 Drew Roedersheimer, Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
*/

-static const char rcsid[] = "$Id: png.c,v 1.3 2002/06/10 21:25:48 chris Exp $";
+#ifndef NO_DISPLAY_WINDOW

+#include
+
+#include "img.h"
+
+static const char rcsid[] = "$Id: png.c,v 1.4 2003/08/25 12:23:43 chris Exp $";
+
+int png_load_hdr(img I) {
+ unsigned char sig[PNG_SIG_LEN];
+ png_structp png_ptr;
+ png_infop info_ptr;
+
+ rewind(I->fp);
+
+ if (fread(sig, sizeof(sig[0]), PNG_SIG_LEN, I->fp) != PNG_SIG_LEN) {
+ return(0);
+ }
+
+ /* Check the PNG signature of the file */
+ if (png_sig_cmp(sig, (png_size_t)0, PNG_SIG_LEN)) {
+ I->err = IE_HDRFORMAT;
+ return 0;
+ }
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+
+ if (png_ptr == NULL) {
+ I->err = IE_HDRFORMAT;
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr == NULL) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ I->err = IE_HDRFORMAT;
+ return 0;
+ }
+
+ rewind(I->fp);
+ png_init_io(png_ptr, I->fp);
+
+ png_read_info(png_ptr, info_ptr);
+
+ I->width = png_get_image_width(png_ptr, info_ptr);
+ I->height = png_get_image_height(png_ptr, info_ptr);
+
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ return(1);
+}
+
+int png_abort_load(img I) {
+ return 1;
+}
+
+int png_load_img(img I) {
+ unsigned char **p, **q;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_uint_32 width, height;
+ int i, j, bit_depth, color_type, interlace_type;
+ png_bytepp row_pointers;
+
+ img_alloc(I);
+
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ NULL, NULL, NULL);
+
+ if (png_ptr == NULL) {
+ I->err = IE_HDRFORMAT;
+ return 0;
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr == NULL) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ I->err = IE_HDRFORMAT;
+ return 0;
+ }
+
+ rewind(I->fp);
+ png_init_io(png_ptr, I->fp);
+
+ png_read_info(png_ptr, info_ptr);
+
+ /* Get image specific data */
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
+
+ /* Convert greyscale images to 8-bit RGB */
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
+ if (bit_depth < 8) {
+ png_set_gray_1_2_4_to_8(png_ptr);
+ }
+ png_set_gray_to_rgb(png_ptr);
+ }
+
+ /* Change paletted images to RGB */
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_expand(png_ptr);
+
+ if (bit_depth < 8)
+ png_set_expand(png_ptr);
+
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+ /* The gdk img widget appears to expect 8-bit RGB followed by a
+ * filler byte. */
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+
+ /* Update the info structure after the transforms */
+ png_read_update_info(png_ptr, info_ptr);
+/* png_set_rows(png_ptr, info_ptr, row_pointers)*/
+
+ /* Allocate space before reading the image */
+ row_pointers = png_malloc(png_ptr, height * sizeof(png_bytep));
+ for (i = 0; i < height; i++) {
+ row_pointers[i] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+ }
+
+ /* Read in the image and copy it to the gdk img structure */
+ png_read_image(png_ptr, row_pointers);
+
+ p = (unsigned char **)I->data;
+ q = (unsigned char **)row_pointers;
+
+ for (i = 0; i < height; i++) {
+ for (j = 0; j < png_get_rowbytes(png_ptr, info_ptr); j++) {
+ p[i][j] = q[i][j];
+ }
+ }
+
+ png_read_end(png_ptr, info_ptr);
+
+ /* Clean up */
+ png_free(png_ptr, row_pointers);
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ return 1;
+}
+
+int png_save_img(const img I, FILE *fp) {
+ return 1;
+}
+
+#endif /* !NO_DISPLAY_WINDOW */
diff -Naur driftnet-0.1.6/util.c driftnet/util.c
--- driftnet-0.1.6/util.c Wed Dec 31 16:00:00 1969
+++ driftnet/util.c Mon Aug 25 05:24:35 2003
@@ -0,0 +1,83 @@
+/*
+ * util.c:
+ * Various utility functions.
+ *
+ * Copyright (c) 2003 Chris Lightfoot. All rights reserved.
+ * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
+ *
+ */
+
+static const char rcsid[] = "$Id: util.c,v 1.2 2003/08/25 12:24:35 chris Exp $";
+
+#include
+#include
+
+#include "driftnet.h"
+
+/* xmalloc COUNT
+ * Malloc, and abort if malloc fails. */
+void *xmalloc(size_t n) {
+ void *v;
+ v = malloc(n);
+ if (!v) abort();
+ return v;
+}
+
+/* xcalloc NITEMS COUNT
+ * As above. */
+void *xcalloc(size_t n, size_t m) {
+ void *v;
+ v = calloc(n, m);
+ if (!v) abort();
+ return v;
+}
+
+/* xrealloc PTR COUNT
+ * As above. */
+void *xrealloc(void *w, size_t n) {
+ void *v;
+ v = realloc(w, n);
+ if (n != 0 && !v) abort();
+ return v;
+}
+
+/* xfree PTR
+ * Free, ignoring a passed NULL value. */
+void xfree(void *v) {
+ if (v) free(v);
+}
+
+/* xstrdup:
+ * Strdup, aborting on failure. */
+char *xstrdup(const char *s) {
+ char *t;
+ t = xmalloc(strlen(s) + 1);
+ strcpy(t, s);
+ return t;
+}
+
+/* memstr:
+ * Locate needle, of length n_len, in haystack, of length h_len, returning NULL.
+ * Uses the Boyer-Moore search algorithm. Cf.
+ * http://www-igm.univ-mlv.fr/~lecroq/string/node14.html */
+unsigned char *memstr(const unsigned char *haystack, const size_t hlen,
+ const unsigned char *needle, const size_t nlen) {
+ int skip[256], k;
+
+ if (nlen == 0) return (char*)haystack;
+
+ /* Set up the finite state machine we use. */
+ for (k = 0; k < 256; ++k) skip[k] = nlen;
+ for (k = 0; k < nlen - 1; ++k) skip[needle[k]] = nlen - k - 1;
+
+ /* Do the search. */
+ for (k = nlen - 1; k < hlen; k += skip[haystack[k]]) {
+ int i, j;
+ for (j = nlen - 1, i = k; j >= 0 && haystack[i] == needle[j]; j--) i--;
+ if (j == -1) return (unsigned char*)(haystack + i + 1);
+ }
+
+ return NULL;
+}
+
+

driftnet _unstable_ port information

Package: driftnet
Version: 0.1.6
Revision: 1025
Maintainer: H. Todd Fujinaka
Depends: libpcap-shlibs, libpng3-shlibs, pango1-xft2-ft219-shlibs (>= 1.18.4-4), libjpeg-shlibs, libiconv, gtk+2-shlibs (>= 2.12.0-1), glib2-shlibs (>= 2.14.0-1), atk1-shlibs (>= 1.20.0-1), giflib-shlibs, x11, libgettext3-shlibs
BuildDepends: glitz, expat1, cairo (>= 1.6-1), fontconfig2-dev (>= 2.4.1-1), freetype219 (>= 2.3.5-1), xft2-dev, libpcap, libpng3, pango1-xft2-ft219-dev (>= 1.18.4-4), pixman (>= 0.10.0-1), libjpeg, libiconv-dev, gtk+2-dev (>= 2.12.0-1), glib2-dev (>= 2.14.0-1), atk1 (>= 1.20.0-1), giflib, x11-dev, libgettext3-dev, pkgconfig (>= 0.21-1)
Replaces: drifnet
Source: http://www.ex-parrot.com/~chris/driftnet/driftnet-%v.tar.gz
Source-MD5: 8e11d77770452f97bb3c23f510489815
PatchScript: <<
#!/bin/sh -ev
sed 's:@PREFIX@:%p:g' <%a/%{n}.patch | patch -p1
<<
NoSetMAKEFLAGS: true
SetMAKEFLAGS: -j1
CompileScript: make PKG_CONFIG_PATH="%p/lib/pango-ft219/lib/pkgconfig:%p/lib/fontconfig2/lib/pkgconfig:%p/lib/freetype219/lib/pkgconfig:$PKG_CONFIG_PATH" FREETYPE_CONFIG=%p/lib/freetype219/bin/freetype-config
InstallScript: <<
#!/bin/sh -ev
install -d -m 755 %i/bin
install -m 755 driftnet %i/bin
install -d -m 755 %i/share/man/man1
install -m 755 driftnet.1 %i/share/man/man1
<<
DocFiles: CHANGES COPYING README CREDITS TODO
Description: Tool for snooping pictures
DescDetail: <<
Driftnet watches network traffic, and picks out and displays JPEG and GIF
images for display. It is an horrific invasion of privacy and shouldn't be used
by anyone anywhere. It can also extract MPEG audio data from the network and
play it. If you live in a house with thick walls, this may be a useful way to
find out about your neighbours' musical taste.
<<
DescUsage: <<
sudo ./driftnet
<<
License: GPL
Homepage: http://www.ex-parrot.com/~chris/driftnet/

driftnet _unstable_ port .patch

diff -Naur driftnet-0.1.6/CHANGES driftnet/CHANGES
--- driftnet-0.1.6/CHANGES Tue Jul 9 12:26:41 2002
+++ driftnet/CHANGES Mon Apr 26 07:42:36 2004
@@ -1,5 +1,16 @@
Changelog for driftnet
-$Id: CHANGES,v 1.16 2002/07/09 17:31:00 chris Exp $
+$Id: CHANGES,v 1.19 2004/04/26 14:42:36 chris Exp $
+
+Driftnet now uses GTK2, rather than GTK1.
+
+Added support for reading packets from a pcap dump file (thanks to Rob Timko
+and Joshua Wright for this); and for extracting URLs from HTTP requests (not
+yet exposed in the user interface).
+
+Driftnet will now discard connections after 8Mb of data has been transferred.
+
+Fixed adjunct mode so that stdout is line-buffered, following a suggestion by
+Jonas Jensen.

0.1.6

diff -Naur driftnet-0.1.6/CREDITS driftnet/CREDITS
--- driftnet-0.1.6/CREDITS Tue Jul 9 12:26:41 2002
+++ driftnet/CREDITS Mon Apr 26 07:42:36 2004
@@ -1,5 +1,5 @@
Credits and contributors for driftnet
-$Id: CREDITS,v 1.6 2002/06/10 21:25:48 chris Exp $
+$Id: CREDITS,v 1.9 2004/04/26 14:42:36 chris Exp $

Thanks to the authors of EtherPEG, for a cool idea, and to Eric Richardson,
whose website brought it to my attention.
@@ -11,4 +11,13 @@

Eric Dobbs for fixing some portability issues and getting driftnet running on
Solaris and BSD systems.
+
+Drew Roedersheimer for contributing PNG support.
+
+Joshua Wright for some 802.11 fixes.
+
+Rob Timko and Joshua Wright for getting Driftnet working on wireless networks
+and reading decrypted data from Kismet.
+
+Bastien Nocera for updating driftnet to use GTK2.

diff -Naur driftnet-0.1.6/Makefile driftnet/Makefile
--- driftnet-0.1.6/Makefile Tue Aug 24 20:33:35 2004
+++ driftnet/Makefile Sat Aug 28 23:36:16 2004
@@ -5,7 +5,7 @@
# Copyright (c) 2001 Chris Lightfoot. All rights reserved.
# Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
#
-# $Id: Makefile,v 1.34 2002/07/09 17:30:42 chris Exp $
+# $Id: Makefile,v 1.41 2004/04/26 14:42:36 chris Exp $
#

#
@@ -20,19 +20,23 @@
LDFLAGS += -g

# You might need these if libpcap is installed somewhere random.
-CFLAGS += -I/usr/include/pcap
+#CFLAGS += -I/usr/include/pcap
#LDFLAGS += -L/path/to/libpcap.so
+# On Mac OS X with Fink etc., try these:
+CFLAGS += -I/usr/include/pcap -I@PREFIX@/include # -I/opt/local/include
+LDFLAGS += -L@PREFIX@/lib/
+#LDFLAGS += -L/opt/local/lib/

# Required on Linux to get BSDish definitions of the TCP/IP structs.
CFLAGS += -D_BSD_SOURCE

# We always need the pcap and pthread libraries.
-LDLIBS += -lpcap -lpthread
+LDLIBS += -lpcap -lpthread #-lefence

# Optional C compiler and linker flags. Typical driftnet builds have support
# for displaying captured images in an X window, and need the following flags:
-CFLAGS += `gtk-config --cflags`
-LDLIBS += -ljpeg -lungif `gtk-config --libs`
+CFLAGS += `pkg-config --cflags gtk+-2.0`
+LDLIBS += -ljpeg -lgif -lpng `pkg-config --libs gtk+-2.0`

# Alternatively, you can build a version of driftnet which can only be used
# in `adjunct' mode as the back end for some other image-processing program. To
@@ -49,7 +53,6 @@
# nanosleep; uncomment the below.
#LDLIBS += -lposix4

-# added 20020604 edobbs
# On BSD systems, may need to use /usr/local/include
#CFLAGS += -I/usr/local/include

@@ -66,7 +69,7 @@

TXTS = README TODO COPYING CHANGES CREDITS driftnet.1 driftnet.1.in endian.c
SRCS = audio.c mpeghdr.c gif.c img.c jpeg.c png.c driftnet.c image.c \
- display.c playaudio.c connection.c media.c
+ display.c playaudio.c connection.c media.c util.c http.c
HDRS = img.h driftnet.h mpeghdr.h
BINS = driftnet

@@ -80,17 +83,17 @@
driftnet.1: driftnet.1.in Makefile
( echo '.\" DO NOT EDIT THIS FILE-- edit driftnet.1.in instead' ; sed s/@@@VERSION@@@/$(VERSION)/ ) < driftnet.1.in > driftnet.1

-endianness: endian
- ./endian > endianness
+endianness.h: endian
+ ./endian > endianness.h

endian: endian.c
$(CC) $(CFLAGS) -o endian endian.c

-%.o: %.c Makefile endianness
- $(CC) $(CFLAGS) `cat endianness` -c -o $@ $<
+%.o: %.c Makefile endianness.h
+ $(CC) $(CFLAGS) -c -o $@ $<

clean: nodepend
- rm -f *~ *.bak *.o core $(BINS) TAGS driftnet.1 endian endianness
+ rm -f *~ *.bak *.o core $(BINS) TAGS driftnet.1 endian endianness.h

tags:
etags *.c *.h
@@ -102,7 +105,7 @@
rm -rf driftnet-$(VERSION)
mv driftnet-$(VERSION).tar.gz ..

-depend: endianness
+depend: endianness.h
makedepend -- $(CFLAGS) `cat endianness` -- $(SRCS)
touch depend
rm -f Makefile.bak
diff -Naur driftnet-0.1.6/README driftnet/README
--- driftnet-0.1.6/README Tue Jul 9 12:26:41 2002
+++ driftnet/README Tue Aug 12 07:03:24 2003
@@ -1,5 +1,5 @@
README for driftnet
-$Id: README,v 1.7 2002/06/10 21:25:48 chris Exp $
+$Id: README,v 1.9 2003/08/12 14:03:24 chris Exp $

Driftnet watches network traffic, and picks out and displays JPEG and GIF
images for display. It is an horrific invasion of privacy and shouldn't be used
@@ -20,6 +20,18 @@

Driftnet needs to run with sufficient privilege to obtain raw packets from the
network. On most systems, this means running it as root.
+
+
+You can use Driftnet to sniff images passing over a wireless network. However,
+Driftnet does not understand the optional WEP encryption used with wireless
+ethernet. Instead, you can use Kismet, from
+ http://www.kismetwireless.net/
+to decrypt packets and pass them into a named pipe; the -f option can then be
+used to have Driftnet read the packets from the pipe. Thanks to Rob Timko and
+Joshua Wright for pointing this out; Rob's page,
+ http://68.38.68.127:81/writings/driftnet.html
+describes the process in greater detail.
+

If you find this program entertaining, you might want to help me develop it.
The TODO file contains a list of yet-to-be-done ideas.
diff -Naur driftnet-0.1.6/TODO driftnet/TODO
--- driftnet-0.1.6/TODO Tue Jul 9 12:26:41 2002
+++ driftnet/TODO Tue Aug 12 07:13:14 2003
@@ -1,5 +1,5 @@
TODO for driftnet
-$Id: TODO,v 1.10 2002/06/04 20:16:35 chris Exp $
+$Id: TODO,v 1.12 2003/08/12 14:13:14 chris Exp $

* PNG files.

@@ -23,4 +23,8 @@
* Safe(r) setuid operation.

* Drop privileges after starting up pcap.
+
+* PID file?
+
+* Delay between reading packets from dump file?

diff -Naur driftnet-0.1.6/connection.c driftnet/connection.c
--- driftnet-0.1.6/connection.c Tue Jul 9 12:26:41 2002
+++ driftnet/connection.c Thu Oct 16 04:56:37 2003
@@ -1,12 +1,15 @@
/*
* connection.c:
+ * Connection objects.
*
* Copyright (c) 2002 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
*/

-static const char rcsid[] = "$Id: connection.c,v 1.3 2002/07/08 23:32:33 chris Exp $";
+static const char rcsid[] = "$Id: connection.c,v 1.7 2003/10/16 11:56:37 chris Exp $";
+
+#include

#include
#include
@@ -16,52 +19,58 @@

#include "driftnet.h"

-/* connection_new:
- * Allocate a new connection structure between the given addresses. */
+/* connection_new SOURCE DEST SPORT DPORT
+ * Allocate a new connection structure for data sent from SOURCE:SPORT to
+ * DEST:DPORT. */
connection connection_new(const struct in_addr *src, const struct in_addr *dst, const short int sport, const short int dport) {
- connection c = (connection)calloc(1, sizeof(struct _connection));
+ connection c;
+ alloc_struct(_connection, c);
c->src = *src;
c->dst = *dst;
c->sport = sport;
c->dport = dport;
c->alloc = 16384;
- c->data = c->gif = c->jpeg = c->mpeg = malloc(c->alloc);
+ c->data = xmalloc(c->alloc);
c->last = time(NULL);
c->blocks = NULL;
return c;
}

-/* connection_delete:
- * Free the named connection structure. */
+/* connection_delete CONNECTION
+ * Free CONNECTION. */
void connection_delete(connection c) {
+ struct datablock *b;
+ for (b = c->blocks; b;) {
+ struct datablock *b2;
+ b2 = b->next;
+ free(b);
+ b = b2;
+ }
free(c->data);
free(c);
}

-/* connection_push:
- * Put some more data in a connection. */
+/* connection_push CONNECTION DATA OFFSET LENGTH
+ * Add LENGTH bytes of DATA received at OFFSET in the stream to CONNECTION. */
void connection_push(connection c, const unsigned char *data, unsigned int off, unsigned int len) {
- size_t goff = c->gif - c->data, joff = c->jpeg - c->data, moff = c->mpeg - c->data;
struct datablock *B, *b, *bl, BZ = {0};
int a;

assert(c->alloc > 0);
if (off + len > c->alloc) {
/* Allocate more memory. */
- while (off + len > c->alloc) {
+ do
c->alloc *= 2;
- c->data = (unsigned char*)realloc(c->data, c->alloc);
- }
+ while (off + len > c->alloc);
+ c->data = (unsigned char*)xrealloc(c->data, c->alloc);
}
- c->gif = c->data + goff;
- c->jpeg = c->data + joff;
- c->mpeg = c->data + moff;
+
memcpy(c->data + off, data, len);

if (off + len > c->len) c->len = off + len;
c->last = time(NULL);

- B = malloc(sizeof *B);
+ B = xmalloc(sizeof *B);
*B = BZ;
B->off = off;
B->len = len;
@@ -95,13 +104,5 @@
}
}
} while (a);
-/*
- {
- printf("%p: ", c);
- for (b = c->blocks; b; b = b->next)
- printf("[%d (%d) -> %d] ", b->off, b->len, b->off + b->len);
- printf("\n");
- }
-*/
}

diff -Naur driftnet-0.1.6/display.c driftnet/display.c
--- driftnet-0.1.6/display.c Tue Jul 9 12:26:41 2002
+++ driftnet/display.c Mon Apr 26 07:42:36 2004
@@ -9,17 +9,21 @@

#ifndef NO_DISPLAY_WINDOW

-static const char rcsid[] = "$Id: display.c,v 1.15 2002/06/13 20:06:42 chris Exp $";
+static const char rcsid[] = "$Id: display.c,v 1.19 2004/04/26 14:42:36 chris Exp $";

-#include
-#include
-#include
+#include
+
+#include
+#include
#include
#include
-#include
-#include
#include
-#include
+#include
+#include
+
+#include
+#include
+#include

#include

@@ -29,7 +33,7 @@
/* The border, in pixels, around images displayed in the window. */
#define BORDER 6

-extern int verbose; /* in driftnet.c */
+extern int verbose, beep; /* in driftnet.c */

static GtkWidget *window, *darea;
static GdkWindow *drawable;
@@ -80,7 +84,7 @@
/* Possible it has scrolled off the window. */
if (ir->x > width || ir->y + ir->h < 0) {
unlink(ir->filename);
- free(ir->filename);
+ xfree(ir->filename);
memset(ir, 0, sizeof *ir);
}
}
@@ -104,7 +108,7 @@
GdkGC *gc;
gc = gdk_gc_new(drawable);
gdk_draw_rgb_32_image(drawable, gc, 0, 0, width, height, GDK_RGB_DITHER_NORMAL, (guchar*)backing_image->flat, sizeof(pel) * width);
- gdk_gc_destroy(gc);
+ g_object_unref(gc);
}
}

@@ -128,7 +132,7 @@
/* scrolled off bottom, no longer in use. */
if ((ir->y + ir->h) < 0) {
unlink(ir->filename);
- free(ir->filename);
+ xfree(ir->filename);
memset(ir, 0, sizeof *ir);
}
}
@@ -145,7 +149,7 @@
break;
}
if (ir == imgrects + nimgrects) {
- imgrects = realloc(imgrects, 2 * nimgrects * sizeof *imgrects);
+ imgrects = xrealloc(imgrects, 2 * nimgrects * sizeof *imgrects);
memset(imgrects + nimgrects, 0, nimgrects * sizeof *imgrects);
ir = imgrects + nimgrects;
nimgrects *= 2;
@@ -172,7 +176,7 @@
* React to an expose event, perhaps changing the backing image size. */
void expose_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
if (darea) drawable = darea->window;
- gdk_window_get_size(drawable, &width, &height);
+ gdk_drawable_get_size(GDK_DRAWABLE(drawable), &width, &height);
if (!backing_image || backing_image->width != width || backing_image->height != height)
make_backing_image();

@@ -183,7 +187,7 @@
* React to a configure event, perhaps changing the backing image size. */
void configure_event(GtkWidget *widget, GdkEvent *event, gpointer data) {
if (darea) drawable = darea->window;
- gdk_window_get_size(drawable, &width, &height);
+ gdk_drawable_get_size(GDK_DRAWABLE(drawable), &width, &height);
if (!backing_image || backing_image->width != width || backing_image->height != height)
make_backing_image();

@@ -205,7 +209,7 @@
struct stat st;

if (!name)
- name = calloc(strlen(savedimgpfx) + 16, 1);
+ name = xcalloc(strlen(savedimgpfx) + 16, 1);

do
sprintf(name, "%s%d%s", savedimgpfx, num++, strrchr(ir->filename, '.'));
@@ -301,10 +305,10 @@
int nimgs = 0;

if (!path)
- path = malloc(strlen(tmpdir) + 34);
+ path = xmalloc(strlen(tmpdir) + 34);

- /* We are sent messages continaing the length of the filename, then the
- * length of the file, then the filename. */
+ /* We are sent messages of size TMPNAMELEN containing a null-terminated
+ * file name. */
while (nimgs < 4 && (rr = xread(dpychld_fd, name, sizeof name)) == sizeof name) {
int saveimg = 0;
struct stat st;
@@ -319,7 +323,7 @@
if (verbose)
fprintf(stderr, PROGNAME": received image %s of size %d\n", name, (int)st.st_size);
/* Check to see whether this looks like an image we're interested in. */
- if (st.st_size > 256) {
+ if (st.st_size > 100) {
/* Small images are probably bollocks. */
img i = img_new();
if (!img_load_file(i, path, header, unknown))
@@ -350,6 +354,9 @@
add_image_rectangle(path, wrx, wry - h, w, h);
saveimg = 1;

+ if (beep)
+ write(1, "\a", 1);
+
update_window();

wrx += w + BORDER;
@@ -383,32 +390,30 @@
fcntl(dpychld_fd, F_SETFL, O_NONBLOCK);

/* set up list of image rectangles. */
- imgrects = calloc(nimgrects = 16, sizeof *imgrects);
+ imgrects = xcalloc(nimgrects = 16, sizeof *imgrects);

/* do some init thing */
gtk_init(&argc, &argv);
- gdk_rgb_init();

- gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
- gtk_widget_set_default_visual(gdk_rgb_get_visual());
+ gtk_widget_push_colormap(gdk_rgb_get_colormap());

/* Make our own window. */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_usize(window, 0, 0);
+ gtk_widget_set_size_request(window, 100, 100);

darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_widget_set_events(darea, GDK_EXPOSURE_MASK|GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);

- gtk_signal_connect(GTK_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
- gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);
+ g_signal_connect(G_OBJECT(window), "delete_event", GTK_SIGNAL_FUNC(delete_event), NULL);
+ g_signal_connect(G_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(destroy), NULL);

- gtk_signal_connect(GTK_OBJECT(darea), "expose-event", GTK_SIGNAL_FUNC(expose_event), NULL);
- gtk_signal_connect(GTK_OBJECT(darea), "configure_event", GTK_SIGNAL_FUNC(expose_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "expose-event", GTK_SIGNAL_FUNC(expose_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "configure_event", GTK_SIGNAL_FUNC(expose_event), NULL);

/* mouse button press/release for saving images */
- gtk_signal_connect(GTK_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_press_event), NULL);
- gtk_signal_connect(GTK_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_release_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_press_event), NULL);
+ g_signal_connect(G_OBJECT(darea), "button_press_event", GTK_SIGNAL_FUNC(button_release_event), NULL);

gtk_widget_show_all(window);

@@ -419,7 +424,11 @@
if (ir->filename)
unlink(ir->filename);

- return 0;
+ img_delete(backing_image);
+
+ gtk_exit(0);
+
+ return 0; /* NOTREACHED */
}

#endif /* !NO_DISPLAY_WINDOW */
diff -Naur driftnet-0.1.6/driftnet.1.in driftnet/driftnet.1.in
--- driftnet-0.1.6/driftnet.1.in Tue Jul 9 12:26:41 2002
+++ driftnet/driftnet.1.in Mon Apr 26 07:42:36 2004
@@ -6,7 +6,7 @@
.\" Copyright (c) 2002 Chris Lightfoot. All rights reserved.
.\" Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
.\"
-.\" $Id: driftnet.1.in,v 1.5 2002/06/04 15:39:54 chris Exp $
+.\" $Id: driftnet.1.in,v 1.7 2004/04/26 14:42:36 chris Exp $
.\"

.SH NAME
@@ -37,6 +37,9 @@
\fB-v\fP
Print additional details of packets captured to the terminal.
.TP
+\fB-b\fP
+Beep when a new image is displayed.
+.TP
\fB-i\fP \fIinterface\fP
Listen to packets on \fIinterface\fP. By default, \fBdriftnet\fP will try to
pick up traffic on all interfaces, but this does not work with all versions of
@@ -101,7 +104,7 @@
.SH VERSION
\fBDriftnet\fP, version @@@VERSION@@@.
.br
-$Id: driftnet.1.in,v 1.5 2002/06/04 15:39:54 chris Exp $
+$Id: driftnet.1.in,v 1.7 2004/04/26 14:42:36 chris Exp $

.SH COPYING
This program is free software; you can redistribute it and/or modify
diff -Naur driftnet-0.1.6/driftnet.c driftnet/driftnet.c
--- driftnet-0.1.6/driftnet.c Tue Jul 9 12:26:41 2002
+++ driftnet/driftnet.c Thu Oct 16 04:56:37 2003
@@ -7,7 +7,7 @@
*
*/

-static const char rcsid[] = "$Id: driftnet.c,v 1.25 2002/07/08 20:57:17 chris Exp $";
+static const char rcsid[] = "$Id: driftnet.c,v 1.32 2003/10/16 11:56:37 chris Exp $";

#undef NDEBUG

@@ -45,9 +45,10 @@
connection *slots;
unsigned int slotsused, slotsalloc;

-/* flags: verbose, adjunct mode, temporary directory to use, media types to extract. */
+/* flags: verbose, adjunct mode, temporary directory to use, media types to
+ * extract, beep on image. */
int extract_images = 1;
-int verbose, adjunct;
+int verbose, adjunct, beep;
int tmpdir_specified;
char *tmpdir;
int max_tmpfiles;
@@ -85,14 +86,14 @@
char *buf;
size_t buflen;

- buf = malloc(buflen = strlen(tmpdir) + 64);
+ buf = xmalloc(buflen = strlen(tmpdir) + 64);

while ((de = readdir(d))) {
char *p;
p = strrchr(de->d_name, '.');
if (!tmpdir_specified || (p && strncmp(de->d_name, "driftnet-", 9) == 0 && (strcmp(p, ".jpeg") == 0 || strcmp(p, ".gif") == 0 || strcmp(p, ".mp3") == 0))) {
if (buflen < strlen(tmpdir) + strlen(de->d_name) + 1)
- buf = realloc(buf, buflen = strlen(tmpdir) + strlen(de->d_name) + 64);
+ buf = xrealloc(buf, buflen = strlen(tmpdir) + strlen(de->d_name) + 64);

sprintf(buf, "%s/%s", tmpdir, de->d_name);
unlink(buf);
@@ -100,7 +101,7 @@
}
closedir(d);

- free(buf);
+ xfree(buf);
}


@@ -116,7 +117,7 @@
if (!*C) return C;
}
/* No connection slots left. */
- slots = (connection*)realloc(slots, slotsalloc * 2 * sizeof(connection));
+ slots = (connection*)xrealloc(slots, slotsalloc * 2 * sizeof(connection));
memset(slots + slotsalloc, 0, slotsalloc * sizeof(connection));
C = slots + slotsalloc;
slotsalloc *= 2;
@@ -141,6 +142,7 @@
/* sweep_connections:
* Free finished connection slots. */
#define TIMEOUT 5
+#define MAXCONNECTIONDATA (8 * 1024 * 1024)

void sweep_connections(void) {
time_t now;
@@ -151,8 +153,11 @@
connection c = *C;
/* We discard connections which have seen no activity for TIMEOUT
* or for which a FIN has been seen and for which there are no
- * gaps in the stream. */
- if ((now - c->last) > TIMEOUT || (c->fin && (!c->blocks || !c->blocks->next))) {
+ * gaps in the stream, or where more than MAXCONNECTIONDATA have
+ * been captured. */
+ if ((now - c->last) > TIMEOUT
+ || (c->fin && (!c->blocks || !c->blocks->next))
+ || c->len > MAXCONNECTIONDATA) {
connection_extract_media(c, extract_type);
connection_delete(c);
*C = NULL;
@@ -212,10 +217,17 @@

case DLT_IEEE802:
return 22;
-
+
+#ifdef DLT_ATM_RFC1483
case DLT_ATM_RFC1483:
return 8;
+#endif

+#ifdef DLT_PRISM_HEADER
+ case DLT_PRISM_HEADER:
+ return 32;
+#endif
+
case DLT_RAW:
return 0;

@@ -229,6 +241,11 @@
return 16;
#endif

+#ifdef DLT_IEEE802_11 /* 802.11 wireless ethernet */
+ case DLT_IEEE802_11:
+ return 32; /* 20030606 email from Nikhil Bobb */ /*44; */
+#endif
+
default:;
}
fprintf(stderr, PROGNAME": unknown data link type %d", type);
@@ -254,8 +271,12 @@
"\n"
" -h Display this help message.\n"
" -v Verbose operation.\n"
+" -b Beep when a new image is captured.\n"
" -i interface Select the interface on which to listen (default: all\n"
" interfaces).\n"
+" -f file Instead of listening on an interface, read captured\n"
+" packets from a pcap dump file; file can be a named pipe\n"
+" for use with Kismet or similar.\n"
" -p Do not put the listening interface into promiscuous mode.\n"" -a Adjunct mode: do not display images on screen, but save\n"
" them to a temporary directory and announce their names on\n"
" standard output.\n"
@@ -294,9 +315,7 @@
}

/* terminate_on_signal:
- * Terminate on receipt of an appropriate signal. This is really ugly, because
- * the pcap_next call in the main loop may block, so it's best to just exit
- * here. */
+ * Terminate on receipt of an appropriate signal. */
sig_atomic_t foad;

void terminate_on_signal(int s) {
@@ -458,7 +477,7 @@
/* main:
* Entry point. Process command line options, start up pcap and enter capture
* loop. */
-char optstring[] = "hi:psSMvam:d:x:";
+char optstring[] = "abd:f:hi:M:m:pSsvx:";

int main(int argc, char *argv[]) {
char *interface = NULL, *filterexpr;
@@ -472,7 +491,10 @@
extern char *audio_mpeg_player; /* in playaudio.c */
int newpfx = 0;
int mpeg_player_specified = 0;
+ char *dumpfile = NULL;
+
pthread_t packetth;
+ connection *C;

/* Handle command-line options. */
opterr = 0;
@@ -483,6 +505,10 @@
return 0;

case 'i':
+ if (dumpfile) {
+ fprintf(stderr, PROGNAME": can't specify -i and -f\n");
+ return -1;
+ }
interface = optarg;
break;

@@ -490,6 +516,13 @@
verbose = 1;
break;

+ case 'b':
+ if (!isatty(1))
+ fprintf(stderr, PROGNAME": can't beep unless standard output is a terminal\n");
+ else
+ beep = 1;
+ break;
+
case 'p':
promisc = 0;
break;
@@ -524,6 +557,14 @@
tmpdir_specified = 1; /* so we don't delete it. */
break;

+ case 'f':
+ if (interface) {
+ fprintf(stderr, PROGNAME": can't specify -i and -f\n");
+ return -1;
+ }
+ dumpfile = optarg;
+ break;
+
#ifndef NO_DISPLAY_WINDOW
case 'x':
savedimgpfx = optarg;
@@ -568,6 +609,15 @@
if (max_tmpfiles && adjunct && verbose)
fprintf(stderr, PROGNAME": a maximum of %d images will be buffered\n", max_tmpfiles);

+ if (beep && adjunct)
+ fprintf(stderr, PROGNAME": can't beep in adjunct mode\n");
+
+ /* In adjunct mode, it's important that the attached program gets
+ * notification of images in a timely manner. Make stdout line-buffered
+ * for this reason. */
+ if (adjunct)
+ setvbuf(stdout, NULL, _IOLBF, 0);
+
/* If a directory name has not been specified, then we need to create one.
* Otherwise, check that it's a directory into which we may write files. */
if (tmpdir) {
@@ -585,10 +635,10 @@
} else {
/* need to make a temporary directory. */
for (;;) {
- tmpdir = strdup(tmpnam(NULL));
+ tmpdir = strdup(tmpnam(NULL)); /* may generate a warning, but this is safe because we create a directory not a file */
if (mkdir(tmpdir, 0700) == 0)
break;
- free(tmpdir);
+ xfree(tmpdir);
}
}

@@ -606,16 +656,20 @@

/* Build up filter. */
if (optind < argc) {
- char **a;
- int l;
- for (a = argv + optind, l = sizeof("tcp and ()"); *a; l += strlen(*a) + 1, ++a);
- filterexpr = calloc(l, 1);
- strcpy(filterexpr, "tcp and (");
- for (a = argv + optind; *a; ++a) {
- strcat(filterexpr, *a);
- if (*(a + 1)) strcat(filterexpr, " ");
+ if (dumpfile)
+ fprintf(stderr, PROGNAME": filter code ignored with dump file\n");
+ else {
+ char **a;
+ int l;
+ for (a = argv + optind, l = sizeof("tcp and ()"); *a; l += strlen(*a) + 1, ++a);
+ filterexpr = calloc(l, 1);
+ strcpy(filterexpr, "tcp and (");
+ for (a = argv + optind; *a; ++a) {
+ strcat(filterexpr, *a);
+ if (*(a + 1)) strcat(filterexpr, " ");
+ }
+ strcat(filterexpr, ")");
}
- strcat(filterexpr, ")");
} else filterexpr = "tcp";

if (verbose)
@@ -662,27 +716,33 @@
#endif /* !NO_DISPLAY_WINDOW */

/* Start up pcap. */
+ if (dumpfile) {
+ if (!(pc = pcap_open_offline(dumpfile, ebuf))) {
+ fprintf(stderr, PROGNAME": pcap_open_offline: %s\n", ebuf);
+ return -1;
+ }
+ } else {
+ if (!(pc = pcap_open_live(interface, SNAPLEN, promisc, 1000, ebuf))) {
+ fprintf(stderr, PROGNAME": pcap_open_live: %s\n", ebuf);

- pc = pcap_open_live(interface, SNAPLEN, promisc, 1000, ebuf);
- if (!pc) {
- fprintf(stderr, PROGNAME": pcap_open_live: %s\n", ebuf);
-
- if (getuid() != 0)
- fprintf(stderr, PROGNAME": perhaps you need to be root?\n");
- else if (!interface)
- fprintf(stderr, PROGNAME": perhaps try selecting an interface with the -i option?\n");
-
- return -1;
- }
-
- if (pcap_compile(pc, &filter, (char*)filterexpr, 1, 0) == -1) {
- fprintf(stderr, PROGNAME": pcap_compile: %s\n", pcap_geterr(pc));
- return -1;
- }
+ if (getuid() != 0)
+ fprintf(stderr, PROGNAME": perhaps you need to be root?\n");
+ else if (!interface)
+ fprintf(stderr, PROGNAME": perhaps try selecting an interface with the -i option?\n");
+
+ return -1;
+ }

- if (pcap_setfilter(pc, &filter) == -1) {
- fprintf(stderr, PROGNAME": pcap_setfilter: %s\n", pcap_geterr(pc));
- return -1;
+ /* Only apply a filter to live packets. Is this right? */
+ if (pcap_compile(pc, &filter, (char*)filterexpr, 1, 0) == -1) {
+ fprintf(stderr, PROGNAME": pcap_compile: %s\n", pcap_geterr(pc));
+ return -1;
+ }
+
+ if (pcap_setfilter(pc, &filter) == -1) {
+ fprintf(stderr, PROGNAME": pcap_setfilter: %s\n", pcap_geterr(pc));
+ return -1;
+ }
}

/* Figure out the offset from the start of a returned packet to the data in
@@ -693,7 +753,7 @@

slotsused = 0;
slotsalloc = 64;
- slots = (connection*)calloc(slotsalloc, sizeof(connection));
+ slots = (connection*)xcalloc(slotsalloc, sizeof(connection));

/* Actually start the capture stuff up. Unfortunately, on many platforms,
* libpcap doesn't have read timeouts, so we start the thing up in a
@@ -724,8 +784,15 @@
pthread_join(packetth, NULL);

/* Clean up. */
+/* pcap_freecode(pc, &filter);*/ /* not on some systems... */
pcap_close(pc);
clean_temporary_directory();
+
+ /* Easier for memory-leak debugging if we deallocate all this here.... */
+ for (C = slots; C < slots + slotsalloc; ++C)
+ if (*C) connection_delete(*C);
+ xfree(slots);
+ xfree(tmpdir);

return 0;
}
diff -Naur driftnet-0.1.6/driftnet.h driftnet/driftnet.h
--- driftnet-0.1.6/driftnet.h Mon Aug 23 22:40:05 2004
+++ driftnet/driftnet.h Thu Apr 8 16:06:29 2004
@@ -5,7 +5,7 @@
* Copyright (c) 2001 Chris Lightfoot. All rights reserved.
* Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
*
- * $Id: driftnet.h,v 1.9 2002/06/13 20:06:42 chris Exp $
+ * $Id: driftnet.h,v 1.13 2004/04/08 23:06:29 chris Exp $
*
*/

@@ -14,18 +14,27 @@

#define PROGNAME "driftnet"

-#include /* added 20020604 edobbs for OpenBSD */
+#include
+
#include
#include
#include
#include
#include
+#ifndef USE_SYS_TYPES_H
+# include
+#endif
+
+/* alloc_struct S P
+ * Make P point to a new struct S, initialised as if in static storage (like
+ * = {0}). */
+#define alloc_struct(S, p) do { struct S as__z = {0}; p = xmalloc(sizeof *p); *p = as__z; } while (0)

/* enum mediatype:
- * Characterise types of media which we can extract. */
-enum mediatype { m_image = 1, m_audio = 2 };
+ * Bit field to characterise types of media which we can extract. */
+enum mediatype { m_image = 1, m_audio = 2, m_text = 4 };

-#define NMEDIATYPES 3 /* keep up to date with media.c */
+#define NMEDIATYPES 5 /* keep up to date with media.c */

/* struct datablock:
* Represents an extent in a captured stream. */
@@ -35,15 +44,27 @@
};

/* connection:
- * Object representing one half of a TCP stream connection. */
+ * Object representing one half of a TCP stream connection. Each connection
+ * maintains a record of the data which has been recovered from the network
+ * and a list of blocks of data which represent valid data in the buffer, so
+ * that if there is a gap in the received data, we don't search it for
+ * data. */
typedef struct _connection {
+ /* Source/destination address/port of this half-duplex connection. */
struct in_addr src, dst;
short int sport, dport;
+ /* The TCP initial-sequence-number of the connection. */
uint32_t isn;
- unsigned int len, off, alloc;
- unsigned char *data, *gif, *jpeg, *mpeg;
+ /* The highest offset and the buffer size allocated, and the buffer
+ * itself. */
+ unsigned int len, alloc;
+ unsigned char *data;
+ /* Flag indicating that we've seen a FIN-flagged segment for this stream,
+ * so that it is undergoing a shutdown. */
int fin;
+ /* The time at which we last received any data on this stream. */
time_t last;
+ /* A list of the extents in the buffer which contain valid data. */
struct datablock *blocks;
} *connection;

@@ -60,6 +81,14 @@

/* media.c */
void connection_extract_media(connection c, const enum mediatype T);
+
+/* util.c */
+void *xmalloc(size_t n);
+void *xcalloc(size_t n, size_t m);
+void *xrealloc(void *w, size_t n);
+void xfree(void *v);
+char *xstrdup(const char *s);
+unsigned char *memstr(const unsigned char *haystack, const size_t hlen, const unsigned char *needle, const size_t nlen);

#define TMPNAMELEN 64

diff -Naur driftnet-0.1.6/endian.c driftnet/endian.c
--- driftnet-0.1.6/endian.c Tue Jul 9 12:26:41 2002
+++ driftnet/endian.c Mon Nov 3 02:40:23 2003
@@ -7,7 +7,7 @@
*
*/

-static const char rcsid[] = "$Id: endian.c,v 1.5 2002/06/10 21:25:48 chris Exp $";
+static const char rcsid[] = "$Id: endian.c,v 1.6 2003/11/03 10:40:23 chris Exp $";

#include
#ifdef USE_SYS_TYPES_H
@@ -18,18 +18,18 @@

int main(void) {
#if defined(LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)
- printf("-DDRIFTNET_LITTLE_ENDIAN\n");
+ printf("#define DRIFTNET_LITTLE_ENDIAN\n");
return 0;
#elif defined(BIG_ENDIAN) || defined(_BIG_ENDIAN)
- printf("-DDRIFTNET_BIG_ENDIAN\n");
+ printf("#define DRIFTNET_BIG_ENDIAN\n");
return 0;
#else
uint32_t a = 0;
*((uint8_t*)&a) = 0xff;
if (a == 0xff000000)
- printf("-DDRIFTNET_BIG_ENDIAN\n");
+ printf("#define DRIFTNET_BIG_ENDIAN\n");
else if (a == 0x000000ff)
- printf("-DDRIFTNET_LITTLE_ENDIAN\n");
+ printf("#define DRIFTNET_LITTLE_ENDIAN\n");
else
return -1; /* don't know. */
#endif /* endianness test */
diff -Naur driftnet-0.1.6/http.c driftnet/http.c
--- driftnet-0.1.6/http.c Wed Dec 31 16:00:00 1969
+++ driftnet/http.c Tue Aug 12 07:14:15 2003
@@ -0,0 +1,124 @@
+/*
+ * http.c:
+ * Look for HTTP requests in buffers.
+ *
+ * We look for GET requests only, and only if the response is of type
+ * text/html.
+ *
+ * Copyright (c) 2003 Chris Lightfoot. All rights reserved.
+ * Email: chris@ex-parrot.com; WWW: http://www.ex-parrot.com/~chris/
+ *
+ */
+
+static const char rcsid[] = "$Id: http.c,v 1.1 2003/08/12 14:14:15 chris Exp $";
+
+#include
+
+#include
+#include
+
+#include "driftnet.h"
+
+/* find_http_req DATA LEN FOUND FOUNDLEN
+ * Look for an HTTP request and response in buffer DATA of length LEN. The
+ * return value is a pointer into DATA suitable for a subsequent call to this
+ * function; *FOUND is either NULL, or a pointer to the start of an HTTP
+ * request; in the latter case, *FOUNDLEN is the length of the match
+ * containing enough information to obtain the URL. */
+unsigned char *find_http_req(const unsigned char *data, const size_t len, unsigned char **http, size_t *httplen) {
+ unsigned char *req, *le, *blankline, *hosthdr;
+
+#define remaining(x) (len - (data - (x)))
+#define MAX_REQ 16384
+
+ /* HTTP requests look like:
+ *
+ * GET {path} HTTP/1.(0|1)\r\n
+ * header: value\r\n
+ * ...
+ * \r\n
+ *
+ * We may care about the Host: header in the request. */
+ if (len < 40)
+ return (unsigned char*)data;
+
+ if (!(req = memstr(data, len, "GET ", 4)))
+ return (unsigned char*)(data + len - 4);
+
+ /* Find the end of the request line. */
+ if (!(le = memstr(req + 4, remaining(req + 4), "\r\n", 2))) {
+ if (remaining(req + 4) > MAX_REQ)
+ return (unsigned char*)(req + 4);
+ else
+ return (unsigned char*)req;
+ }
+
+ /* Not enough space for a path. */
+ if (le < req + 5)
+ return le + 2;
+
+ /* Not an HTTP request, just a line starting GET.... */
+ if (memcmp(le - 9, " HTTP/1.", 8) || !strchr("01", (int)*(le - 1)))
+ return le + 2;
+
+ /* Find the end of the request headers. */
+ if (!(blankline = memstr(le + 2, remaining(le + 2), "\r\n\r\n", 4))) {
+ if (remaining(le + 2) > MAX_REQ)
+ return (unsigned char*)(data + len - 4);
+ else
+ return req;
+ }
+
+ if (memcmp(req + 4, "http://", 7) == 0)
+ /* Probably a cache request; in any case, don't need to look for a Host:. */
+ goto found;
+
+ /* Is there a Host: header? */
+ if (!(hosthdr = memstr(le, blankline - le + 2, "\r\nHost: ", 8))) {
+ return blankline + 4;
+ }
+
+found:
+
+ *http = req;
+ *httplen = blankline - req;
+
+ return blankline + 4;
+}
+
+void dispatch_http_req(const char *mname, const unsigned char *data, const size_t len) {
+ char *url;
+ const char *path, *host;
+ int pathlen, hostlen;
+ const unsigned char *p;
+
+ if (!(p = memstr(data, len, "\r\n", 2)))
+ return;
+
+ path = (const char*)(data + 4);
+ pathlen = (p - 9) - (unsigned char*)path;
+
+ if (memcmp(path, "http://", 7) == 0) {
+ url = malloc(pathlen + 1);
+ sprintf(url, "%.*s", pathlen, path);
+ } else {
+
+ if (!(p = memstr(p, len - (p - data), "\r\nHost: ", 8)))
+ return;
+
+ host = (const char*)(p + 8);
+
+ if (!(p = memstr(p + 8, len - (p + 8 - data), "\r\n", 2)))
+ return;
+ hostlen = p - (const unsigned char*)host;
+
+ if (hostlen == 0)
+ return;
+
+ url = malloc(hostlen + pathlen + 9);
+ sprintf(url, "http://%.*s%.*s", hostlen, host, pathlen, path);
+ }
+
+ fprintf(stderr, "\n\n %s\n\n", url);
+ free(url);
+}
diff -Naur driftnet-0.1.6/image.c driftnet/image.c
--- driftnet-0.1.6/image.c Tue Jul 9 12:26:41 2002
+++ driftnet/image.c Mon Aug 25 05:23:43 2003
@@ -7,40 +7,20 @@
*
*/

-static const char rcsid[] = "$Id: image.c,v 1.10 2002/07/02 22:17:25 chris Exp $";
+static const char rcsid[] = "$Id: image.c,v 1.13 2003/08/25 12:23:43 chris Exp $";

#include
#include
#include
+#include

-/* memstr:
- * Locate needle, of length n_len, in haystack, of length h_len, returning NULL.
- * Uses the Boyer-Moore search algorithm. Cf.
- * http://www-igm.univ-mlv.fr/~lecroq/string/node14.html */
-static unsigned char *memstr(const unsigned char *haystack, const size_t hlen,
- const unsigned char *needle, const size_t nlen) {
- int skip[256], k;
-
- if (nlen == 0) return (char*)haystack;
-
- /* Set up the finite state machine we use. */
- for (k = 0; k < 255; ++k) skip[k] = nlen;
- for (k = 0; k < nlen - 1; ++k) skip[needle[k]] = nlen - k - 1;
-
- /* Do the search. */
- for (k = nlen - 1; k < hlen; k += skip[haystack[k]]) {
- int i, j;
- for (j = nlen - 1, i = k; j >= 0 && haystack[i] == needle[j]; j--) i--;
- if (j == -1) return (unsigned char*)(haystack + i + 1);
- }
-
- return NULL;
-}
+#include "img.h"

+#include "driftnet.h"

/* If we run out of space, put us back to the last candidate GIF header. */
/*#define spaceleft do { if (block > data + len) { printf("ran out of space\n"); return gifhdr; } } while (0)*/
-#define spaceleft if (block > data + len) return gifhdr
+#define spaceleft if (block >= data + len) return gifhdr /* > ?? */

unsigned char *find_gif_image(const unsigned char *data, const size_t len, unsigned char **gifdata, size_t *giflen) {
unsigned char *gifhdr, *block;
@@ -59,6 +39,7 @@
ncolours = (1 << ((gifhdr[10] & 0x7) + 1));
/* printf("gif header %d colours\n", ncolours); */
block = gifhdr + 13;
+ spaceleft;
if (gifhdr[10] & 0x80) block += 3 * ncolours; /* global colour table */
spaceleft;

@@ -68,9 +49,12 @@
case 0x2c:
/* image block */
/* printf("image data\n"); */
- if (block[9] & 0x80)
+ if (block + 9 > data + len) return gifhdr;
+ if (block[9] & 0x80) {
/* local colour table */
block += 3 * ((1 << ((gifhdr[9] & 0x7) + 1)));
+ spaceleft;
+ }
block += 10;
++block; /* lzw code size */
do {
@@ -195,7 +179,7 @@
if (!block || (block - data) >= len) return jpeghdr;

/* now we need to find the onward count from this place */
- while ((block = jpeg_skip_block(block + 1, len - (block - data)))) {
+ while ((block = jpeg_skip_block(block + 1, len - (block + 1 - data)))) {
/* printf("data = %p block = %p\n", data, block); */

block = jpeg_next_marker(block, len - (block - data));
@@ -217,6 +201,64 @@
/* printf("nope, no complete JPEG here\n"); */
return jpeghdr;
}
+
+/* find_png_eoi BUFFER LEN
+ * Returns the first position in BUFFER of LEN bytes after the end of the image
+ * or NULL if end of image not found. */
+unsigned char *find_png_eoi(unsigned char *buffer, const size_t len) {
+ unsigned char *end_data, *data, chunk_code[PNG_CODE_LEN + 1];
+ struct png_chunk chunk;
+ u_int32_t datalen;
+
+ /* Move past the PNG header */
+ data = (buffer + PNG_SIG_LEN);
+ end_data = (buffer + len - (sizeof(struct png_chunk) + PNG_CRC_LEN));
+
+ while (data <= end_data) {
+ memcpy(&chunk, data, sizeof chunk);
+/* chunk = (struct png_chunk *)data; */ /* can't do that. */
+ memset(chunk_code, '\0', PNG_CODE_LEN + 1);
+ memcpy(chunk_code, chunk.code, PNG_CODE_LEN);
+
+ datalen = ntohl(chunk.datalen);
+
+ if (!strncasecmp(chunk_code, "iend", PNG_CODE_LEN))
+ return (unsigned char *)(data + sizeof(struct png_chunk) + PNG_CRC_LEN);
+
+ /* Would this push us off the end of the buffer? */
+ if (datalen > (len - (data - buffer)))
+ return NULL;
+
+ data += (sizeof(struct png_chunk) + datalen + PNG_CRC_LEN);
+ }
+
+ return NULL;
+}
+
+/* find_png_image DATA LEN PNGDATA PNGLEN
+ * Look for PNG images in LEN bytes buffer DATA. */
+unsigned char *find_png_image(const unsigned char *data, const size_t len, unsigned char **pngdata, size_t *pnglen) {
+ unsigned char *pnghdr, *data_end, *png_eoi;
+
+ *pngdata = NULL;
+
+ if (len < PNG_SIG_LEN)
+ return (unsigned char*)data;
+
+ pnghdr = memstr(data, len, "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", PNG_SIG_LEN);
+ if (!pnghdr)
+ return (unsigned char*)(data + len - PNG_SIG_LEN);
+
+ data_end = (unsigned char *)(data + len);
+
+ if ((png_eoi = find_png_eoi(pnghdr, (data_end - pnghdr))) == NULL)
+ return pnghdr;
+
+ *pngdata = pnghdr;
+ *pnglen = (png_eoi - pnghdr);
+ return png_eoi;
+}
+

#if 0
#include
diff -Naur driftnet-0.1.6/img.c driftnet/img.c
--- driftnet-0.1.6/img.c Tue Jul 9 12:26:41 2002
+++ driftnet/img.c Mon Aug 25 05:23:43 2003
@@ -9,12 +9,13 @@

#ifndef NO_DISPLAY_WINDOW

-static const char rcsid[] = "$Id: img.c,v 1.9 2002/07/08 20:57:17 chris Exp $";
+static const char rcsid[] = "$Id: img.c,v 1.11 2003/08/25 12:23:43 chris Exp $";

#include
#include
#include

+#include "driftnet.h"
#include "img.h"

#define INLINE inline
@@ -38,6 +39,12 @@
int jpeg_load_img(img I);
int jpeg_save_img(const img I, FILE *fp);

+/* png.c */
+int png_load_hdr(img I);
+/*int png_abort_load(img I);*/
+int png_load_img(img I);
+/*int png_save_img(const img I, FILE *fp);*/
+
#if 0
/* raw.c */
int raw_load_img(img I);
@@ -59,8 +66,9 @@
*/
{gif, ".gif\0", gif_load_hdr, gif_abort_load, gif_load_img, NULL},
{jpeg, ".jpg\0.jp