- Martin Pels' patch to allow UDP probes.
- KES reported a build problem. Turns out I need to install gtk-1.2
on my development sytem, otherwise my release script causes the
build to break.
- changed some docs to advertise the new mailing list. added
documentation for the Mac OS X compilation problem. added
-Wno-pointer-sign to the compiler options.
- Nico Lichtmaier's cleanup-gtk patch. (now mtr uses a more modern
dialect of gtk).
source: ftp://ftp.bitwizard.nl/mtr/mtr-0.74.tar.gz
WHAT'S NEW?
+ v0.74 Martin Pels' patch to allow UDP probes.
+ KES reported a build problem. Turns out I need to install gtk-1.2
+ on my development sytem, otherwise my release script causes the
+ build to break.
+ changed some docs to advertise the new mailing list.
+ added documentation for the Mac OS X compilation problem.
+ added -Wno-pointer-sign to the compiler options.
+ Nico Lichtmaier's cleanup-gtk patch. (now mtr uses a more modern
+ dialect of gtk).
+ v0.73 Some securty patches. Although MTR drops privileges as soon
+ as possible after opening the sockets, it still had some
+ sprintf calls, which have now been converted into snprintf.
v0.72 Fix signed/unsigned bug in IPV6 part
improved random packet size behaviour. --REW
v0.71 Some IPV6 fixes, introduce packet size cmdline option.
Note that mtr must be suid-root because it requires access to raw IP
sockets. See SECURITY for security information.
- If you want to build a version that doesn't use GTK, but if you
- DO have GTK installed, you can use
-
- ./configure --with-gtk-prefix=/we_dont_want_gtk_so_we_use_a_name_that_certainly_doesnt_exist
-
- It seems the --no_gtk (whatever) doesn't work. Feel free to submit
- a patch for this, I'm not that familiar with autoconf (it works for
- me :-).
+ Older versions used to require a non-existant path to GTK for a
+ correct build of a non-gtk version while GTK was installed. This is
+ no longer neccesary. ./configure --WITHOUT_GTK should now work.
+ If it doesn't, try "make WITHOUT_X11=YES" as the make step.
On Solaris (and possibly other systems) the "gtk" library may be
installed in a directory where the dynamic linker refuses to look when
doing the linking into a terminal window, and add "-lcurses" by hand.
Then it will link. Help on how to catch this in autoconf appreciated.
+ On Mac OS X the nameserver8_compat.h needs to be included. I put the
+ include inside an "#if 0" section in the file "dns.c". If someone
+ knows how to make this automatic using autoconf / the configure script,
+ please tell me....
+
WHERE CAN I GET THE LATEST VERSION OR MORE INFORMATION?
Subscribe to the mtr mailing list. All mtr related announcements
are posted to the mtr mailing list. To subscribe, send email to
- 'majordomo@lists.xmission.com' with 'subscribe mtr' in the body of
- the message. To send a message to the mailing list, mail to
- 'mtr@lists.xmission.com'.
+ the 'mtr-subscribe' with the hostname part set to 'BitWizard.nl'.
+ The body or subject of the message doesn't matter. To send an
+ Email to the list, mail to the username part set to 'mtr'. To
+ prevent SPAM to this list, please don't put the full name on
+ the internet.
- Bug reports and feature requests should be submitted into the
- jitterbug bug-tracking system at http://www.BitWizard.nl/cgi-bin/mtr .
- If you don't have web-access, mail the mailinglist.
+ Bug reports and feature requests should be submitted the mailing
+ list.
Patches can be submitted by Email to me, or submitted to the
- bug tracking system. Please use unified diffs.
+ mailing list. Please use unified diffs. Usually the diff is sort of
+ messy, so please check that the diff is clean and doesn't contain too
+ much of your local stuff (for example, I don't want/need the "configure"
+ script that /your/ automake made for you).
-- REW
AC_INIT(mtr.c)
-AM_INIT_AUTOMAKE(mtr, 0.73)
+AM_INIT_AUTOMAKE(mtr, 0.74)
AC_SUBST(GTK_OBJ)
AC_CHECK_LIB(curses, initscr, ,
AC_CHECK_LIB(cursesX, initscr, ,
AC_MSG_WARN(Building without curses display support)
- AC_DEFINE(NO_CURSES)
+ AC_DEFINE(NO_CURSES, 1, Define if you don't have the curses libraries available.)
CURSES_OBJ=))))
AC_CHECK_FUNCS(attron)
[ --without-gtk Do not try to use GTK+ at all],
WANTS_GTK=$withval, WANTS_GTK=yes)
-AC_ARG_ENABLE(gtk2,
-[ --enable-gtk2 Compile against GTK2 instead of GTK+],
-WANTS_GTK2=$enableval, WANTS_GTK2=no)
-
AC_ARG_ENABLE(ipv6,
[ --disable-ipv6 Do not enable IPv6],
WANTS_IPV6=$enableval, WANTS_IPV6=yes)
if test "x$WANTS_GTK" = "xyes"; then
- if test "x$WANTS_GTK2" = "xyes"; then
- AM_PATH_GTK_2_0(2.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS"
+ AM_PATH_GTK_2_0(2.4.0, CFLAGS="$CFLAGS $GTK_CFLAGS"
LIBS="$LIBS $GTK_LIBS -lm",
AC_MSG_WARN(Building without GTK2 display support)
- AC_DEFINE(NO_GTK)
- GTK_OBJ="")
- else
- AM_PATH_GTK(1.0.0, CFLAGS="$CFLAGS $GTK_CFLAGS"
- LIBS="$LIBS $GTK_LIBS",
- AC_MSG_WARN(Building without GTK+ display support)
- AC_DEFINE(NO_GTK)
+ AC_DEFINE(NO_GTK, 1, [Define if you don't have the GTK+ libraries available.])
GTK_OBJ="")
- fi
else
AC_DEFINE(NO_GTK)
GTK_OBJ=""
# removing it hurts your OS.... -- REW
#LIBS="$LIBS -lresolv"
-AC_CHECK_FUNC(herror, , AC_DEFINE(NO_HERROR))
-AC_CHECK_FUNC(strerror, , AC_DEFINE(NO_STRERROR))
+AC_CHECK_FUNC(herror, , AC_DEFINE(NO_HERROR, 1, [Define if you don't have the herror() function available.]))
+AC_CHECK_FUNC(strerror, , AC_DEFINE(NO_STRERROR, 1, [Define if you don't have the strerror() function available.]))
AC_CHECK_FUNC(getaddrinfo,
[if test "$WANTS_IPV6" = "yes"; then
dnl Add C flags to display more warnings
AC_MSG_CHECKING(for C flags to get more warnings)
ac_save_CFLAGS="$CFLAGS"
-if test "x$ac_cv_prog_gcc" = "xyes" ; then
+if test "x$ac_cv_c_compiler_gnu" = "xyes" ; then
dnl gcc is the easiest C compiler
- warning_CFLAGS="-Wall"
+ warning_CFLAGS="-Wall -Wno-pointer-sign"
else
dnl Vendor supplied C compilers are a bit tricky
case "$host_os" in
dnl SGI IRIX with the MipsPRO C compiler
irix*)
CFLAGS="$CFLAGS -fullwarn"
- AC_TRY_COMPILE([#include <stdio.h>],[printf("test");],
- warning_CFLAGS="-fullwarn",)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[printf("test");]])],[warning_CFLAGS="-fullwarn"],[])
;;
dnl SunOS 4.x with the SparcWorks(?) acc compiler
sunos*)
if "$CC" = "acc" ; then
CFLAGS="$CFLAGS -vc"
- AC_TRY_COMPILE([#include <stdio.h>],[printf("test");],
- warning_CFLAGS="-vc",)
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stdio.h>]], [[printf("test");]])],[warning_CFLAGS="-vc"],[])
fi
;;
-AM_CONFIG_HEADER(config.h)
-AC_OUTPUT(Makefile img/Makefile)
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_FILES([Makefile img/Makefile])
+AC_OUTPUT
extern int tos;
extern float WaitTime;
extern int af;
+extern int mtrtype;
void pwcenter(char *str)
{
}
return ActionNone;
}
+ if (tolower(c) == 'u') {
+ switch ( mtrtype ) {
+ case IPPROTO_ICMP:
+ mtrtype = IPPROTO_UDP;
+ break;
+ case IPPROTO_UDP:
+ mtrtype = IPPROTO_ICMP;
+ break;
+ }
+ return ActionNone;
+ }
/* reserve to display help message -Min */
if (tolower(c) == '?'|| tolower(c) == 'h') {
mvprintw(2, 0, "Command:\n" );
printw(" m <n> set the max time-to-live, default n= # of hops\n" );
printw(" s <n> set the packet size to n or random(n<0)\n" );
printw(" b <c> set ping bit pattern to c(0..255) or random(c<0)\n" );
- printw(" Q <t> set ping packet's TOS to t\n\n\n" );
+ printw(" Q <t> set ping packet's TOS to t\n" );
+ printw(" u switch between ICMP ECHO and UDP datagrams\n\n" );
mvprintw(16, 0, " press any key to go back..." );
getch(); /* get any key */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+
#define BIND_8_COMPAT
#include <arpa/nameser.h>
#include <netdb.h>
#include "dns.h"
#include "net.h"
+/* OSX Needs this. I don't know how to enable this for them automatically.
+ * Should be easy with autoconf. Please submit a patch if you know
+ * autoconf.... -- REW
+ */
+#if 0
+#include "nameser8_compat.h"
+#endif
+
+
#ifdef NO_STRERROR
extern int sys_nerr;
extern char *sys_errlist[];
}
-struct hostent * dns_forward(char *name)
+struct hostent * dns_forward(const char *name)
{
struct hostent *host;
void dns_events(double *sinterval);
char *dns_lookup(ip_t * address);
char *dns_lookup2(ip_t * address);
-struct hostent * dns_forward(char *name);
+struct hostent * dns_forward(const char *name);
char *strlongip(ip_t * ip);
void addr2ip6arpa( ip_t * ip, char * buf );
int dt;
dt = calc_deltatime (WaitTime);
- tag = gtk_timeout_add(dt / 1000, gtk_ping, NULL);
+ tag = g_timeout_add(dt / 1000, gtk_ping, NULL);
}
if (paused) {
gtk_add_ping_timeout ();
} else {
- gtk_timeout_remove (tag);
+ g_source_remove (tag);
}
paused = ! paused;
gtk_redraw();
gint WaitTime_changed(UNUSED GtkAdjustment *Adj, UNUSED GtkWidget *Button)
{
- WaitTime = gtk_spin_button_get_value_as_float(GTK_SPIN_BUTTON(Button));
- gtk_timeout_remove (tag);
+ WaitTime = gtk_spin_button_get_value(GTK_SPIN_BUTTON(Button));
+ g_source_remove (tag);
gtk_add_ping_timeout ();
gtk_redraw();
net_reopen(addr);
/* If we are "Paused" at this point it is usually because someone
entered a non-existing host. Therefore do the go-ahead... --REW */
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( Pause_Button ) , 0);
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( Pause_Button ) , 0);
} else {
- gtk_toggle_button_set_state( GTK_TOGGLE_BUTTON( Pause_Button ) , 1);
- gtk_entry_append_text( GTK_ENTRY(Entry), ": not found" );
+ int pos = strlen(gtk_entry_get_text( GTK_ENTRY(Entry)));
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( Pause_Button ) , 1);
+ gtk_editable_insert_text( GTK_EDITABLE(Entry), ": not found", -1, &pos);
}
return FALSE;
GtkWidget *Entry;
GtkAdjustment *Adjustment;
- Button = gtk_button_new_with_label("Quit");
+ Button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
- gtk_signal_connect(GTK_OBJECT(Button), "clicked",
+ g_signal_connect(GTK_OBJECT(Button), "clicked",
GTK_SIGNAL_FUNC(Window_destroy), NULL);
- gtk_widget_show(Button);
- Button = gtk_button_new_with_label("Restart");
+ Button = gtk_button_new_with_mnemonic("_Restart");
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
- gtk_signal_connect(GTK_OBJECT(Button), "clicked",
+ g_signal_connect(GTK_OBJECT(Button), "clicked",
GTK_SIGNAL_FUNC(Restart_clicked), NULL);
- gtk_widget_show(Button);
- Pause_Button = gtk_toggle_button_new_with_label("Pause");
+ Pause_Button = gtk_toggle_button_new_with_mnemonic("_Pause");
gtk_box_pack_end(GTK_BOX(Toolbar), Pause_Button, FALSE, FALSE, 0);
- gtk_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
+ g_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
GTK_SIGNAL_FUNC(Pause_clicked), NULL);
- gtk_widget_show(Pause_Button);
/* allow root only to set zero delay */
Adjustment = (GtkAdjustment *)gtk_adjustment_new(WaitTime,
- getuid()==0 ? 0.00:1.00,
+ getuid()==0 ? 0.01:1.00,
999.99,
1.0, 10.0,
0.0);
/* gtk_spin_button_set_set_update_policy(GTK_SPIN_BUTTON(Button),
GTK_UPDATE_IF_VALID); */
gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
- gtk_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
+ g_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
GTK_SIGNAL_FUNC(WaitTime_changed), Button);
- gtk_widget_show(Button);
- Label = gtk_label_new("Hostname");
+ Label = gtk_label_new_with_mnemonic("_Hostname:");
gtk_box_pack_start(GTK_BOX(Toolbar), Label, FALSE, FALSE, 0);
- gtk_widget_show(Label);
Entry = gtk_entry_new();
gtk_entry_set_text(GTK_ENTRY(Entry), Hostname);
- gtk_signal_connect(GTK_OBJECT(Entry), "activate",
+ g_signal_connect(GTK_OBJECT(Entry), "activate",
GTK_SIGNAL_FUNC(Host_activate), NULL);
gtk_box_pack_start(GTK_BOX(Toolbar), Entry, TRUE, TRUE, 0);
- gtk_widget_show(Entry);
-}
-
-
-char *Report_Text[] = { "Hostname", "Loss", "Rcv", "Snt", "Last", "Best", "Avg", "Worst", "StDev", NULL };
-int Report_Positions[] = { 10, 200, 240, 280, 320, 360, 400, 440, 480, 0 };
-GtkWidget *Report;
-GtkWidget *ReportBody;
-
-GtkWidget *GetRow(int index)
-{
- ip_t * addr;
- char *name;
- GtkWidget *Row, *Label;
-
- Row = gtk_fixed_new();
- addr = net_addr(index);
- name = "???";
- if ( addrcmp( (void *) addr, (void *) &unspec_addr, af ) != 0 ) {
- name = dns_lookup(addr);
- if(!name) {
- /* Actually this is not neccesary:
- dns_lookup always returns a printable string */
- name = strlongip (addr);
- }
- }
-
- Label = gtk_label_new(name);
- gtk_fixed_put(GTK_FIXED(Row), Label, Report_Positions[0], 0);
- gtk_widget_show(Label);
-
- return Row;
+ gtk_label_set_mnemonic_widget(GTK_LABEL(Label), Entry);
}
-
-GtkWidget *Scrollarea_create(void)
+static GtkWidget *ReportTreeView;
+static GtkListStore *ReportStore;
+
+enum {
+ COL_HOSTNAME,
+ COL_LOSS,
+ COL_RCV,
+ COL_SNT,
+ COL_LAST,
+ COL_BEST,
+ COL_AVG,
+ COL_WORST,
+ COL_STDEV,
+ COL_COLOR,
+ N_COLS
+};
+
+void float_formatter(GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
{
- GtkWidget *List;
- GtkWidget *scroll;
- int count;
-
- for(count = 0; Report_Positions[count]; count++);
-
- List = GTK_WIDGET(gtk_clist_new_with_titles(count, Report_Text));
- scroll = gtk_scrolled_window_new(NULL, NULL);
- gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
- for(count = 0; Report_Positions[count + 1]; count++) {
- gtk_clist_set_column_width(GTK_CLIST(List), count,
- Report_Positions[count + 1] -
- Report_Positions[count]);
- }
- gtk_clist_set_column_width(GTK_CLIST(List), count, 0);
- for(count = 1; Report_Positions[count]; count++) {
- gtk_clist_set_column_justification(GTK_CLIST(List), count, GTK_JUSTIFY_RIGHT);
- }
- gtk_container_add(GTK_CONTAINER(scroll), List);
- gtk_widget_show(List);
-
- ReportBody = List;
- return scroll;
+ gfloat f;
+ gchar text[64];
+ gtk_tree_model_get(tree_model, iter, (gint)data, &f, -1);
+ sprintf(text, "%.2f", f);
+ g_object_set(cell, "text", text, NULL);
}
-
-void gtk_add_row(GtkWidget *List)
+void percent_formatter(GtkTreeViewColumn *tree_column,
+ GtkCellRenderer *cell,
+ GtkTreeModel *tree_model,
+ GtkTreeIter *iter,
+ gpointer data)
{
- int at;
- GtkWidget *Row, *Label;
-
- Row = gtk_fixed_new();
-
- for(at = 0; Report_Positions[at] != 0; at++) {
- Label = gtk_label_new("-");
- if(at) {
- gtk_widget_set_usize(Label, 40, 0);
- gtk_label_set_justify(GTK_LABEL(Label), GTK_JUSTIFY_RIGHT);
- }
- gtk_fixed_put(GTK_FIXED(Row), Label, Report_Positions[at], 0);
- gtk_widget_show(Label);
- }
-
- gtk_box_pack_start(GTK_BOX(List), Row, FALSE, FALSE, 0);
- gtk_widget_show(Row);
+ gfloat f;
+ gchar text[64];
+ gtk_tree_model_get(tree_model, iter, (gint)data, &f, -1);
+ sprintf(text, "%.1f%%", f);
+ g_object_set(cell, "text", text, NULL);
}
-
-void gtk_set_field(GtkCList *List, int row, int ix, char *str) {
- gtk_clist_set_text(List, row, ix, str);
-}
-
-
-/* void gtk_set_field_num(GtkCList *List, int row, int ix, char *format, int num) {
- changed int to dobule byMin */
-void gtk_set_field_num(GtkCList *List, int row, int ix, char *format, double num)
+void TreeViewCreate(void)
{
- char str[32];
+ GtkCellRenderer *renderer;
+ GtkTreeViewColumn *column;
+
+ ReportStore = gtk_list_store_new(N_COLS,
+ G_TYPE_STRING,
+ G_TYPE_FLOAT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_INT,
+ G_TYPE_FLOAT,
+ G_TYPE_STRING
+ );
+
+ ReportTreeView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore));
+
+ renderer = gtk_cell_renderer_text_new ();
+ column = gtk_tree_view_column_new_with_attributes ("Hostname",
+ renderer,
+ "text", COL_HOSTNAME,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_expand(column, TRUE);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Loss",
+ renderer,
+ "text", COL_LOSS,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_column_set_cell_data_func(column, renderer, percent_formatter, (void*)COL_LOSS, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Rcv",
+ renderer,
+ "text", 2,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Snt",
+ renderer,
+ "text", 3,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Last",
+ renderer,
+ "text", 4,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Best",
+ renderer,
+ "text", 5,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Avg",
+ renderer,
+ "text", 6,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("Worst",
+ renderer,
+ "text", 7,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
+
+ renderer = gtk_cell_renderer_text_new ();
+ g_object_set (G_OBJECT(renderer), "xalign", 1.0, NULL);
+ column = gtk_tree_view_column_new_with_attributes ("StDev",
+ renderer,
+ "text", 8,
+ "foreground", COL_COLOR,
+ NULL);
+ gtk_tree_view_column_set_resizable(column, TRUE);
+ gtk_tree_view_column_set_cell_data_func(column, renderer, float_formatter, (void*)COL_STDEV, NULL);
+ gtk_tree_view_append_column (GTK_TREE_VIEW(ReportTreeView), column);
- sprintf(str, format, num);
- gtk_set_field(List, row, ix, str);
}
-
-void gtk_update_row(GtkCList *List, int row)
+void update_tree_row(int row, GtkTreeIter *iter)
{
ip_t *addr;
char str[256], *name;
- GdkColor color;
- GdkColormap *cmap;
addr = net_addr(row);
name = "???";
}
}
- cmap = gtk_widget_get_colormap(ReportBody);
- if (net_up(row)) {
- gdk_color_black(cmap, &color);
- } else {
- color.red = 0xffff;
- color.green = 0;
- color.blue = 0;
- }
- gdk_color_alloc (cmap, &color);
- gtk_clist_set_foreground(List, row, &color);
+ gtk_list_store_set(ReportStore, iter,
+ COL_HOSTNAME, name,
+ COL_LOSS, (float)(net_loss(row)/1000.0),
- /* changed the format type and added stdev and first/max TTL byMin */
- /* the row - net_min() is kind of not clean, need some more work */
- gtk_set_field(List, row - net_min(), 0, name);
+ COL_RCV, net_returned(row),
+ COL_SNT, net_xmit(row),
- gtk_set_field_num(List, row - net_min(), 1, "%.1f%%", net_loss(row)/1000.0);
- gtk_set_field_num(List, row - net_min(), 2, "%.0f", net_returned(row));
- gtk_set_field_num(List, row - net_min(), 3, "%.0f", net_xmit(row));
-
- gtk_set_field_num(List, row - net_min(), 4, "%.0f", net_last(row)/1000.0);
- gtk_set_field_num(List, row - net_min(), 5, "%.0f", net_best(row)/1000.0);
- gtk_set_field_num(List, row - net_min(), 6, "%.0f", net_avg(row)/1000.0);
- gtk_set_field_num(List, row - net_min(), 7, "%.0f", net_worst(row)/1000.0);
- gtk_set_field_num(List, row - net_min(), 8, "%.2f", net_stdev(row)/1000.0);
-}
+ COL_LAST, net_last(row)/1000,
+ COL_BEST, net_best(row)/1000,
+ COL_AVG, net_avg(row)/1000,
+ COL_WORST, net_worst(row)/1000,
+ COL_STDEV, (float)(net_stdev(row)/1000.0),
+
+ COL_COLOR, net_up(row) ? "black" : "red",
+ -1);
+}
void gtk_redraw(void)
{
- int at = net_min(); /* changed from 0 to net_min for TTL stuff byMin */
int max = net_max();
-
- gtk_clist_freeze(GTK_CLIST(ReportBody));
-
- while(GTK_CLIST(ReportBody)->rows < max -at) { /* byMin */
- gtk_clist_append(GTK_CLIST(ReportBody), Report_Text);
- }
-
- while(GTK_CLIST(ReportBody)->rows > max) {
- gtk_clist_remove(GTK_CLIST(ReportBody), GTK_CLIST(ReportBody)->rows - 1);
+
+ GtkTreeIter iter;
+ int row = net_min();
+ gboolean valid;
+
+ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ReportStore), &iter);
+
+ while(valid) {
+ if(row < max) {
+ update_tree_row(row++, &iter);
+ valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(ReportStore), &iter);
+ } else {
+ valid = gtk_list_store_remove(ReportStore, &iter);
+ }
}
-
- /* for(at=0; at < max; at++) { replaced byMin */
- for(; at < max; at++) {
- gtk_update_row(GTK_CLIST(ReportBody), at);
+ while(row < max) {
+ gtk_list_store_append(ReportStore, &iter);
+ update_tree_row(row++, &iter);
}
-
- gtk_clist_thaw(GTK_CLIST(ReportBody));
}
{
GtkWidget *VBox;
GtkWidget *Toolbar;
- GtkWidget *List;
+ GtkWidget *scroll;
gtk_window_set_title(GTK_WINDOW(Window), "My traceroute [v" VERSION "]");
- gtk_window_set_wmclass(GTK_WINDOW(Window), "mtr", "Mtr");
- gtk_widget_set_usize(Window, 600, 400);
- gtk_container_border_width(GTK_CONTAINER(Window), 10);
+ gtk_window_set_default_size(GTK_WINDOW(Window), 650, 400);
+ gtk_container_set_border_width(GTK_CONTAINER(Window), 10);
VBox = gtk_vbox_new(FALSE, 10);
Toolbar = gtk_hbox_new(FALSE, 10);
Toolbar_fill(Toolbar);
gtk_box_pack_start(GTK_BOX(VBox), Toolbar, FALSE, FALSE, 0);
- gtk_widget_show(Toolbar);
-
- List = Scrollarea_create();
- gtk_box_pack_start(GTK_BOX(VBox), List, TRUE, TRUE, 0);
- gtk_widget_show(List);
+ TreeViewCreate();
+ scroll = gtk_scrolled_window_new(NULL, NULL);
+ gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll), GTK_SHADOW_IN);
+ gtk_container_add(GTK_CONTAINER(scroll), ReportTreeView);
+ gtk_box_pack_start(GTK_BOX(VBox), scroll, TRUE, TRUE, 0);
+
gtk_container_add(GTK_CONTAINER(Window), VBox);
- gtk_widget_show(VBox);
}
Window_fill(Window);
- gtk_signal_connect_object(GTK_OBJECT(Window), "delete_event",
- GTK_SIGNAL_FUNC(gtk_widget_destroy),
- GTK_OBJECT(Window));
- gtk_signal_connect(GTK_OBJECT(Window), "destroy",
+ g_signal_connect(GTK_OBJECT(Window), "delete_event",
+ GTK_SIGNAL_FUNC(Window_destroy), NULL);
+ g_signal_connect(GTK_OBJECT(Window), "destroy",
GTK_SIGNAL_FUNC(Window_destroy), NULL);
icon = gtk_load_pixmap(mtr_icon);
- gtk_widget_show(Window);
+ gtk_widget_show_all(Window);
gdk_window_set_icon(Window->window, NULL, icon, NULL);
gdk_window_set_icon_name(Window->window, "mtr");
}
{
gtk_redraw();
net_send_batch();
- gtk_timeout_remove (tag);
+ g_source_remove (tag);
gtk_add_ping_timeout ();
return TRUE;
}
-void gtk_net_data(UNUSED gpointer data, UNUSED gint fd, UNUSED GdkInputCondition cond)
+gboolean gtk_net_data(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, UNUSED gpointer data)
{
net_process_return();
+ return TRUE;
}
-void gtk_dns_data(UNUSED gpointer data, UNUSED gint fd, UNUSED GdkInputCondition cond)
+gboolean gtk_dns_data(UNUSED GIOChannel *channel, UNUSED GIOCondition cond, UNUSED gpointer data)
{
dns_ack();
gtk_redraw();
+ return TRUE;
}
void gtk_loop(void)
{
+ GIOChannel *net_iochannel, *dns_iochannel;
+
gtk_add_ping_timeout ();
- gdk_input_add(net_waitfd(), GDK_INPUT_READ, gtk_net_data, NULL);
- gdk_input_add(dns_waitfd(), GDK_INPUT_READ, gtk_dns_data, NULL);
+
+ net_iochannel = g_io_channel_unix_new(net_waitfd());
+ g_io_add_watch(net_iochannel, G_IO_IN, gtk_net_data, NULL);
+ dns_iochannel = g_io_channel_unix_new(dns_waitfd());
+ g_io_add_watch(dns_iochannel, G_IO_IN, gtk_dns_data, NULL);
gtk_main();
}
.SH SYNOPSIS
.B mtr
[\c
-.B \-hvrctglspni46\c
+.B \-hvrctglspniu46\c
]
[\c
.B \-\-help\c
Use this option to specify the positive number of seconds between ICMP
ECHO requests. The default value for this parameter is one second.
+.TP
+.B \-u
+.br
+Use UDP datagrams instead of ICMP ECHO.
+
.TP
.B \-4
.br
int bitpattern = 0;
int tos = 0;
int af = DEFAULT_AF;
+int mtrtype = IPPROTO_ICMP; /* Use ICMP as default packet type */
/* begin ttl windows addByMin */
int fstTTL = 1; /* default start at first hop */
{ "address", 1, 0, 'a' },
{ "first-ttl", 1, 0, 'f' }, /* -f & -m are borrowed from traceroute */
{ "max-ttl", 1, 0, 'm' },
+ { "udp", 0, 0, 'u' }, /* UDP (default is ICMP) */
{ "inet", 0, 0, '4' }, /* IPv4 only */
{ "inet6", 0, 0, '6' }, /* IPv6 only */
{ 0, 0, 0, 0 }
while(1) {
/* added f:m:o: byMin */
opt = getopt_long(argc, argv,
- "vhrxtglpo:i:c:s:b:Q:na:f:m:46", long_options, NULL);
+ "vhrxtglpo:i:c:s:b:Q:na:f:m:u46", long_options, NULL);
if(opt == -1)
break;
exit (1);
}
}
- strcpy (fld_active, optarg);
+ strcpy ((char*)fld_active, optarg);
break;
case 'b':
bitpattern = atoi (optarg);
tos = 0;
}
break;
+ case 'u':
+ mtrtype = IPPROTO_UDP;
+ break;
case '4':
af = AF_INET;
break;
parse_arg (argc, argv);
+ /* Now that we know mtrtype we can select which socket to use */
+ if (net_selectsocket() != 0) {
+ fprintf( stderr, "mtr: Couldn't determine raw socket type.\n" );
+ exit( EXIT_FAILURE );
+ }
+
if (PrintVersion) {
printf ("mtr " VERSION "\n");
exit(0);
}
if (PrintHelp) {
- printf("usage: %s [-hvrctglspni46] [--help] [--version] [--report]\n"
+ printf("usage: %s [-hvrctglspniu46] [--help] [--version] [--report]\n"
"\t\t[--report-cycles=COUNT] [--curses] [--gtk]\n"
"\t\t[--raw] [--split] [--no-dns] [--address interface]\n" /* BL */
"\t\t[--psize=bytes/-s bytes]\n" /* ok */
/* Typedefs */
+#if 0
+
+// Neat trick! However, on my system, "config.h" already defines these types
+// so I get a compiler error if I leave this in. -- REW
+
+/* Find the proper type for 8 bits */
+#if SIZEOF_UNSIGNED_CHAR == 1
+typedef unsigned char uint8;
+#else
+#error No 8 bit type
+#endif
+
+/* Find the proper type for 16 bits */
+#if SIZEOF_UNSIGNED_SHORT == 2
+typedef unsigned short uint16;
+#elif SIZEOF_UNSIGNED_INT == 2
+typedef unsigned int uint16;
+#elif SIZEOF_UNSIGNED_LONG == 2
+typedef unsigned long uint16;
+#else
+#error No 16 bit type
+#endif
+
+/* Find the proper type for 32 bits */
+#if SIZEOF_UNSIGNED_SHORT == 4
+typedef unsigned short uint32;
+#elif SIZEOF_UNSIGNED_INT == 4
+typedef unsigned int uint32;
+#elif SIZEOF_UNSIGNED_LONG == 4
+typedef unsigned long uint32;
+#else
+#error No 32 bit type
+#endif
+
+#endif
+
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long dword;
uint16 sequence;
};
+/* Structure of an UDP header. */
+struct UDPHeader {
+ uint16 srcport;
+ uint16 dstport;
+ uint16 length;
+ uint16 checksum;
+};
+
+/* Structure of an IPv4 UDP pseudoheader. */
+struct UDPv4PHeader {
+ uint32 saddr;
+ uint32 daddr;
+ uint8 zero;
+ uint8 protocol;
+ uint16 len;
+};
/* Structure of an IP header. */
struct IPHeader {
#define ICMP_TSTAMPREPLY 14
#define ICMP_TIME_EXCEEDED 11
+#define ICMP_UNREACHABLE 3
#ifndef SOL_IP
#define SOL_IP 0
int timestamp;
int sendsock4;
+int sendsock4_icmp;
+int sendsock4_udp;
int recvsock4;
int sendsock6;
+int sendsock6_icmp;
+int sendsock6_udp;
int recvsock6;
int sendsock;
int recvsock;
extern int bitpattern; /* packet bit pattern used by ping */
extern int tos; /* type of service set in ping packet*/
extern int af; /* address family of remote target */
-
+extern int mtrtype; /* type of query packet used */
/* return the number of microseconds to wait before sending the next
ping */
}
+/* Prepend pseudoheader to the udp datagram and calculate checksum */
+int udp_checksum(void *pheader, void *udata, int psize, int dsize)
+{
+ unsigned int tsize = psize + dsize;
+ char csumpacket[tsize];
+ memset(csumpacket, (unsigned char) abs(bitpattern), abs(tsize));
+
+ struct UDPv4PHeader *prepend = (struct UDPv4PHeader *) csumpacket;
+ struct UDPv4PHeader *udppheader = (struct UDPv4PHeader *) pheader;
+ prepend->saddr = udppheader->saddr;
+ prepend->daddr = udppheader->daddr;
+ prepend->zero = 0;
+ prepend->protocol = udppheader->protocol;
+ prepend->len = udppheader->len;
+
+ struct UDPHeader *content = (struct UDPHeader *)(csumpacket + psize);
+ struct UDPHeader *udpdata = (struct UDPHeader *) udata;
+ content->srcport = udpdata->srcport;
+ content->dstport = udpdata->dstport;
+ content->length = udpdata->length;
+ content->checksum = udpdata->checksum;
+
+ return checksum(csumpacket,tsize);
+}
+
+
int new_sequence(int index)
{
- static int next_sequence = 0;
+ static int next_sequence = MinSequence;
int seq;
seq = next_sequence++;
if (next_sequence >= MaxSequence)
- next_sequence = 0;
+ next_sequence = MinSequence;
sequence[seq].index = index;
sequence[seq].transit = 1;
/*ok char packet[sizeof(struct IPHeader) + sizeof(struct ICMPHeader)];*/
char packet[MAXPACKET];
struct IPHeader *ip = (struct IPHeader *) packet;
- struct ICMPHeader *icmp;
+ struct ICMPHeader *icmp = NULL;
+ struct UDPHeader *udp = NULL;
+ struct UDPv4PHeader *udpp = NULL;
+ uint16 mypid;
/*ok int packetsize = sizeof(struct IPHeader) + sizeof(struct ICMPHeader) + datasize;*/
int rv;
static int first=1;
- int ttl, iphsize = 0, echotype = 0, salen = 0;
+ int ttl, iphsize = 0, echotype = 0, salen = 0, udphsize = 0;
ttl = index + 1;
+ /* offset for ipv6 checksum calculation */
+ int offset = 6;
+
if ( packetsize < MINPACKET ) packetsize = MINPACKET;
if ( packetsize > MAXPACKET ) packetsize = MAXPACKET;
ip->id = 0;
ip->frag = 0; /* 1, if want to find mtu size? Min */
ip->ttl = ttl;
- ip->protocol = IPPROTO_ICMP;
+ ip->protocol = mtrtype;
ip->check = 0;
/* BSD needs the source address here, Linux & others do not... */
#endif
}
- icmp = (struct ICMPHeader *)(packet + iphsize);
- icmp->type = echotype;
- icmp->code = 0;
- icmp->checksum = 0;
- icmp->id = getpid();
- icmp->sequence = new_sequence(index);
- icmp->checksum = checksum(icmp, abs(packetsize) - iphsize);
+ switch ( mtrtype ) {
+ case IPPROTO_ICMP:
+ icmp = (struct ICMPHeader *)(packet + iphsize);
+ icmp->type = echotype;
+ icmp->code = 0;
+ icmp->checksum = 0;
+ icmp->id = getpid();
+ icmp->sequence = new_sequence(index);
+ icmp->checksum = checksum(icmp, abs(packetsize) - iphsize);
+
+ gettimeofday(&sequence[icmp->sequence].time, NULL);
+ break;
+
+ case IPPROTO_UDP:
+ udp = (struct UDPHeader *)(packet + iphsize);
+ udphsize = sizeof (struct UDPHeader);
+ udp->checksum = 0;
+ mypid = (uint16)getpid();
+ if (mypid < MinPort)
+ mypid += MinPort;
+
+ udp->srcport = htons(mypid);
+ udp->length = abs(packetsize) - iphsize;
+ if(!BSDfix)
+ udp->length = htons(udp->length);
+
+ udp->dstport = new_sequence(index);
+ gettimeofday(&sequence[udp->dstport].time, NULL);
+ udp->dstport = htons(udp->dstport);
+ break;
+ }
switch ( af ) {
case AF_INET:
+ switch ( mtrtype ) {
+ case IPPROTO_UDP:
+ /* checksum is not mandatory. only calculate if we know ip->saddr */
+ if (ip->saddr) {
+ udpp = (struct UDPv4PHeader *)(malloc(sizeof(struct UDPv4PHeader)));
+ udpp->saddr = ip->saddr;
+ udpp->daddr = ip->daddr;
+ udpp->protocol = ip->protocol;
+ udpp->len = udp->length;
+ udp->checksum = udp_checksum(udpp, udp, sizeof(struct UDPv4PHeader), abs(packetsize) - iphsize);
+ }
+ break;
+ }
+
ip->check = checksum(packet, abs(packetsize));
break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ switch ( mtrtype ) {
+ case IPPROTO_UDP:
+ /* kernel checksum calculation */
+ if ( setsockopt(sendsock, IPPROTO_IPV6, IPV6_CHECKSUM, &offset, sizeof(offset)) ) {
+ perror( "setsockopt IPV6_CHECKSUM" );
+ exit( EXIT_FAILURE);
+ }
+ break;
+ }
+ break;
+#endif
}
- gettimeofday(&sequence[icmp->sequence].time, NULL);
-
rv = sendto(sendsock, packet, abs(packetsize), 0,
remotesockaddr, salen);
if (first && (rv < 0) && ((errno == EINVAL) || (errno == EMSGSIZE))) {
socklen_t fromsockaddrsize;
int num;
struct ICMPHeader *header = NULL;
+ struct UDPHeader *udpheader = NULL;
struct timeval now;
ip_t * fromaddress = NULL;
- int echoreplytype = 0, timeexceededtype = 0;
+ int echoreplytype = 0, timeexceededtype = 0, unreachabletype = 0;
+ int sequence = 0;
gettimeofday(&now, NULL);
switch ( af ) {
fromaddress = (ip_t *) &(fsa4->sin_addr);
echoreplytype = ICMP_ECHOREPLY;
timeexceededtype = ICMP_TIME_EXCEEDED;
+ unreachabletype = ICMP_UNREACHABLE;
break;
#ifdef ENABLE_IPV6
case AF_INET6:
fromaddress = (ip_t *) &(fsa6->sin6_addr);
echoreplytype = ICMP6_ECHO_REPLY;
timeexceededtype = ICMP6_TIME_EXCEEDED;
+ unreachabletype = ICMP6_DST_UNREACH;
break;
#endif
}
break;
#endif
}
- if (header->type == echoreplytype) {
- if(header->id != (uint16)getpid())
- return;
-
- net_process_ping (header->sequence, (void *) fromaddress, now);
- } else if (header->type == timeexceededtype) {
- switch ( af ) {
- case AF_INET:
- if ((size_t) num < sizeof(struct IPHeader) +
- sizeof(struct ICMPHeader) +
- sizeof (struct IPHeader) +
- sizeof (struct ICMPHeader))
+ switch ( mtrtype ) {
+ case IPPROTO_ICMP:
+ if (header->type == echoreplytype) {
+ if(header->id != (uint16)getpid())
return;
- header = (struct ICMPHeader *)(packet + sizeof (struct IPHeader) +
- sizeof (struct ICMPHeader) +
- sizeof (struct IPHeader));
- break;
+
+ sequence = header->sequence;
+ } else if (header->type == timeexceededtype) {
+ switch ( af ) {
+ case AF_INET:
+
+ if ((size_t) num < sizeof(struct IPHeader) +
+ sizeof(struct ICMPHeader) +
+ sizeof (struct IPHeader) +
+ sizeof (struct ICMPHeader))
+ return;
+ header = (struct ICMPHeader *)(packet + sizeof (struct IPHeader) +
+ sizeof (struct ICMPHeader) +
+ sizeof (struct IPHeader));
+ break;
#ifdef ENABLE_IPV6
- case AF_INET6:
- if ( num < sizeof (struct ICMPHeader) +
- sizeof (struct ip6_hdr) + sizeof (struct ICMPHeader) )
+ case AF_INET6:
+ if ( num < sizeof (struct ICMPHeader) +
+ sizeof (struct ip6_hdr) + sizeof (struct ICMPHeader) )
+ return;
+ header = (struct ICMPHeader *) ( packet +
+ sizeof (struct ICMPHeader) +
+ sizeof (struct ip6_hdr) );
+ break;
+#endif
+ }
+
+ if (header->id != (uint16)getpid())
return;
- header = (struct ICMPHeader *) ( packet +
- sizeof (struct ICMPHeader) +
- sizeof (struct ip6_hdr) );
+
+ sequence = header->sequence;
+ }
+ break;
+
+ case IPPROTO_UDP:
+ if (header->type == timeexceededtype || header->type == unreachabletype) {
+ switch ( af ) {
+ case AF_INET:
+
+ if ((size_t) num < sizeof(struct IPHeader) +
+ sizeof(struct ICMPHeader) +
+ sizeof (struct IPHeader) +
+ sizeof (struct UDPHeader))
+ return;
+ udpheader = (struct UDPHeader *)(packet + sizeof (struct IPHeader) +
+ sizeof (struct ICMPHeader) +
+ sizeof (struct IPHeader));
break;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ if ( num < sizeof (struct ICMPHeader) +
+ sizeof (struct ip6_hdr) + sizeof (struct UDPHeader) )
+ return;
+ udpheader = (struct UDPHeader *) ( packet +
+ sizeof (struct ICMPHeader) +
+ sizeof (struct ip6_hdr) );
+ break;
#endif
+ }
+ sequence = ntohs(udpheader->dstport);
}
-
- if (header->id != (uint16)getpid())
- return;
-
- net_process_ping(header->sequence, (void *)fromaddress, now);
+ break;
}
+
+ if (sequence)
+ net_process_ping(sequence, (void *)fromaddress, now);
}
int trueopt = 1;
#if !defined(IP_HDRINCL) && defined(IP_TOS) && defined(IP_TTL)
- sendsock4 = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ sendsock4_icmp = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ sendsock4_udp = socket(AF_INET, SOCK_RAW, IPPROTO_UDP);
#else
sendsock4 = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
#endif
if (sendsock4 < 0)
return -1;
#ifdef ENABLE_IPV6
- sendsock6 = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ sendsock6_icmp = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ sendsock6_udp = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP);
#endif
#ifdef IP_HDRINCL
return 0;
}
-
+
+int net_selectsocket(void)
+{
+#if !defined(IP_HDRINCL) && defined(IP_TOS) && defined(IP_TTL)
+ switch ( mtrtype ) {
+ case IPPROTO_ICMP:
+ sendsock4 = sendsock4_icmp;
+ break;
+ case IPPROTO_UDP:
+ sendsock4 = sendsock4_udp;
+ break;
+ }
+#endif
+ if (sendsock4 < 0)
+ return -1;
+#ifdef ENABLE_IPV6
+ switch ( mtrtype ) {
+ case IPPROTO_ICMP:
+ sendsock6 = sendsock6_icmp;
+ break;
+ case IPPROTO_UDP:
+ sendsock6 = sendsock6_udp;
+ break;
+ }
+ if (sendsock6 < 0)
+ return -1;
+#endif
+
+ return 0;
+}
+
+
int net_open(struct hostent * host)
{
#ifdef ENABLE_IPV6
void net_close(void)
{
- if (sendsock4 >= 0) close(sendsock4);
+ if (sendsock4 >= 0) {
+ close(sendsock4_icmp);
+ close(sendsock4_udp);
+ }
if (recvsock4 >= 0) close(recvsock4);
- if (sendsock6 >= 0) close(sendsock6);
+ if (sendsock6 >= 0) {
+ close(sendsock6_icmp);
+ close(sendsock6_udp);
+ }
if (recvsock6 >= 0) close(recvsock6);
}
#endif
int net_preopen(void);
+int net_selectsocket(void);
int net_open(struct hostent *host);
void net_reopen(struct hostent *address);
int net_set_interfaceaddress (char *InterfaceAddress);
#define MAXPATH 8
#define MaxHost 256
+#define MinSequence 33000
#define MaxSequence 65536
+#define MinPort 1024
-#define MAXPACKET 4470 /* largest test ICMP packet size */
-#define MINPACKET 28 /* 20 bytes IP header and 8 bytes ICMP */
+#define MAXPACKET 4470 /* largest test packet size */
+#define MINPACKET 28 /* 20 bytes IP header and 8 bytes ICMP or UDP */
/* stuff used by display such as report, curses... --Min */
#define MAXFLD 20 /* max stats fields to display */