Codebase list mtr / 7d211f4
New upstream version 0.94 Samuel Henrique 3 years ago
36 changed file(s) with 505 addition(s) and 440 deletion(s). Raw diff Collapse all Expand all
1010
1111 The "raw" format is:
1212
13 hostline|xmitline|pingline|dnsline|timestampline
13 hostline|xmitline|pingline|dnsline|timestampline|mplsline
1414
1515 hostline:
1616 h <pos> <host IP>
2727 timestampline:
2828 t <pos> <pingtime> <timestamp>
2929
30 mplsline:
31 m <pos> <label> <traffic_class> <bottom_stack> <ttl>
3032
3133 Timestampline is not yet implemented. Need to find out how to do
3234 ICMP timestamping first. :-)
5454 ui/select.c ui/select.h \
5555 ui/utils.c ui/utils.h \
5656 packet/cmdparse.c packet/cmdparse.h \
57 packet/sockaddr.c packet/sockaddr.h \
5758 ui/mtr-curses.h \
5859 img/mtr_icon.xpm \
5960 ui/mtr-gtk.h
8384 mtr_SOURCES += ui/gtk.c
8485 endif
8586
87 if WITH_LIBASAN
88 ASAN_CFLAGS = -fno-omit-frame-pointer
89 ASAN_CFLAGS += -fsanitize=undefined
90 ASAN_CFLAGS += -fsanitize=address
91 endif
92
8693 mtr_INCLUDES = $(GLIB_CFLAGS) -I$(top_builddir) -I$(top_srcdir)
87 mtr_CFLAGS = $(GTK_CFLAGS) $(NCURSES_CFLAGS)
88 mtr_LDADD = $(GTK_LIBS) $(NCURSES_LIBS) $(RESOLV_LIBS)
94 mtr_CFLAGS = $(GTK_CFLAGS) $(NCURSES_CFLAGS) $(ASAN_CFLAGS) $(JANSSON_CFLAGS)
95 mtr_LDADD = $(GTK_LIBS) $(NCURSES_LIBS) $(RESOLV_LIBS) $(JANSSON_LIBS)
8996
9097
9198 mtr_packet_SOURCES = \
33 the commit messages here.
44
55 #NEW_STUFF_HERE this is a tag my script looks for.
6 V0.94
7 Aaron Lipinski (10):
8 gtk_menu_append -> gtk_menu_shell_append
9 GTK_OBJECT -> G_OBJECT
10 gtk_button_new_from_stock -> gtk_button_new_with_label
11 gtk3
12 hbox/vbox -> gtk_box_new
13 gtk_menu_popup -> gtk_menu_popup_at_pointer
14 show resolved hostname in raw dnsline
15 rely on final return NULL
16 introduce libasan
17 avoid stack use after scope
18
19 Alejandro Leal (2):
20 few updates to manual page and README.md
21 Updating some comments
22
23 Chongyu Zhu (1):
24 probe: fix find_source_addr
25
26 Konrad Bucheli (1):
27 fix segmentation fault if there is no IP address on an interface (fixes #320)
28
29 Kulemin Alexander (1):
30 report: json: reworked with libjansson
31
32 Mark Egan-Fuller (1):
33 Add display of destination.
34
35 Markus Kötter (6):
36 simplification - remove sockaddrtop
37 simplification - remove addrcpy
38 simplification - remove rsa{4,6}
39 simplification - address addrcmp
40 simplification - improve readability
41 ip6 udp - fix probes with local or remote port
42
43 R.E. Wolff (29):
44 fix warning on recent compilers.
45 Merge branch 'master' of github.com:traviscross/mtr
46 net find local address fix by meingtsla
47 proposed patch for bsd compile error
48 fix closing brace
49 Added include errno --obouizi
50 Merge branch 'master' of github.com:traviscross/mtr
51 More compilation warning fixes from obouizi
52 Added extra help text to configure --yvs
53 Changed MAXPATH to MAX_PATH for AIX compatibility. -- aixtools
54 make the code for gtk2/3 a bit nicer.
55 Merge branch 'gtk3_with_fallback' of https://github.com/krisl/mtr
56 Merge branch 'master' of github.com:traviscross/mtr
57 in hindsight my previous patch wasn't so nice. And nobody told me.
58
59 Sean Wei (1):
60 Fix parameter in ui/net.c
61
62 Siyuan Miao (1):
63 show mpls information in raw output
64
65 atib (1):
66 Added code to print multiple addresses regitered on the same hop count
67
68 atibdialpad (2):
69 Change TTL dynamically to adjust for path changes
70 TODO list changes
71
72 meingtsla (2):
73 asn_{open,close}: Always initialize ipinfo hash table
74 Merge branch 'master' of https://github.com/traviscross/mtr into asn-open-always-hcreate
75
676 V0.93
777 Adam (1):
878 Update README
3030
3131 ./bootstrap.sh && ./configure && make
3232
33 When it looks as if the compilation was succesful, you can
33 When it looks as if the compilation was successful, you can
3434 test mtr with
3535
3636 sudo ./mtr <host>
4040 - Keep all packets and make the "best" and "worst" columns show the
4141 xx-th percentile....
4242
43 - Can the reports generated also include any secondary servers? In
44 the interactive mode, any new servers that are found in the
45 traceroute are added to the list, but it seems to only include
46 one set of servers when using the -r option.
47
4843 - Being able to expand the "column width" of the hosts listed would
4944 be nice, too.
45
46 - Display per host stats when multiple servers respond at a particular
47 hop count.
5048
5149
5250 - Bugs to fix?
2020 AC_PROG_CC
2121
2222 # Check pkg-config availability.
23 m4_ifndef([PKG_PROG_PKG_CONFIG],
24 [m4_fatal(
23 m4_ifndef([PKG_CHECK_MODULES], [m4_defun([PKG_CHECK_MODULES], [AC_MSG_ERROR(
2524 [Could not locate the pkg-config autoconf macros. These are usually located
2625 in /usr/share/aclocal/pkg.m4. If your macros are in a different location,
2726 try setting the environment variable ACLOCAL_OPTS="-I/other/macro/dir"
28 before running ./bootstrap.sh again.])
27 before running ./bootstrap.sh again, or configure --without-gtk ----without-jansson ])])
2928 ])
3029 PKG_PROG_PKG_CONFIG
3130
8382
8483 AC_CHECK_LIB([m], [floor], [], [AC_MSG_ERROR([No math library found])])
8584
85 # libasan
86 AC_ARG_WITH([libasan],
87 [AS_HELP_STRING([--with-libasan], [Build with AddressSanitizer])],
88 [with_libasan=yes], [])
89 AM_CONDITIONAL([WITH_LIBASAN], [test "x$with_libasan" = "xyes"])
90
8691 # Find GTK
8792 AC_ARG_WITH([gtk],
88 [AS_HELP_STRING([--without-gtk], [Build without the GTK+2.0 interface])],
93 [AS_HELP_STRING([--without-gtk], [Build without the GTK+ interface])],
8994 [], [with_gtk=yes])
9095 AS_IF([test "x$with_gtk" = "xyes"],
91 [PKG_CHECK_MODULES([GTK], [gtk+-2.0],
92 [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+-2.0 library available])],
93 [with_gtk=no])
96 [PKG_CHECK_MODULES([GTK], [gtk+-3.0],
97 [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+ library available])]
98 [AC_DEFINE([HAVE_GTK3], [1], [Define if gtk+-3.0 library available])],
99 [PKG_CHECK_MODULES([GTK], [gtk+-2.0],
100 [AC_DEFINE([HAVE_GTK], [1], [Define if gtk+ library available])],
101 [with_gtk=no])])
94102 ])
95103 AM_CONDITIONAL([WITH_GTK], [test "x$with_gtk" = xyes])
104
105 AC_ARG_WITH([jansson],
106 [AS_HELP_STRING([--without-jansson], [Build without JSON output])],
107 [], [with_jansson=yes])
108 AS_IF([test "x$with_jansson" = "xyes"],
109 [PKG_CHECK_MODULES([JANSSON], [jansson],
110 [AC_DEFINE([HAVE_JANSSON], [1], [Define if jansson library available])],
111 [with_jansson=no])
112 ])
96113
97114 # Find ncurses
98115 AC_ARG_WITH([ncurses],
244261 AM_CONDITIONAL([BUILD_BASH_COMPLETION], [test "x$enable_bash_completion" = xyes])
245262 echo "build options:"
246263 echo "--------------"
264 echo "libasan :$with_libasan"
247265 echo "ipv6 :$USES_IPV6"
248266 echo "ipinfo :$with_ipinfo"
249267 echo "ncurses :$with_ncurses"
250268 echo "gtk :$with_gtk"
269 echo "jansson :$with_jansson"
251270 echo "cap :$have_cap"
252271 echo "libs :$LIBS"
253272 echo "cflags :$CFLAGS"
120120 .I IP-ADDRESS
121121 .HP 14
122122 .IP
123 The local Internet Procol version 4 address to use when sending probes.
123 The local Internet Protocol version 4 address to use when sending probes.
124124 .HP 7
125125 .IP
126126 .B local-ip-6
406406 \&...
407407 .RE 0
408408 .LP
409 Each interemediate host would respond with a
409 Each intermediate host would respond with a
410410 .B ttl-expired
411411 message, and the destination host would respond with a
412412 .BR reply :
137137 of a bad (or simply overloaded) link.
138138 .PP
139139 The results are usually reported as round-trip-response times in milliseconds
140 and the percentage of packetloss.
140 and the percentage of packet loss.
141141 .SH OPTIONS
142142 .TP
143143 .B \-h\fR, \fB\-\-help
266266 .B mtr
267267 to use the JSON output format. This format is better suited for
268268 automated processing of the measurement results.
269 Jansson library must have been available on the system when
270 .B mtr
271 was built for this to work.
269272 .TP
270273 .B \-p\fR, \fB\-\-split
271274 Use this option to set
6565 structure for later semantic interpretation. Returns EINVAL if the
6666 command string is unparseable or zero for success.
6767
68 comamnd_string will be modified in-place with NUL characters terminating
69 tokens, and the command_t will use pointers to the conents of
68 command_string will be modified in-place with NUL characters terminating
69 tokens, and the command_t will use pointers to the contents of
7070 command_string without copying, so any interpretation of the
7171 command_t structure requires that the command_string memory has not yet
7272 been freed or otherwise reused.
723723 /*
724724 Check the current socket address, and if it is the same
725725 as the source address we intend, we will skip the bind.
726 This is to accomodate Solaris, which, as of Solaris 11.3,
726 This is to accommodate Solaris, which, as of Solaris 11.3,
727727 will return an EINVAL error on bind if the socket is already
728728 bound, even if the same address is used.
729729 */
753753 }
754754 }
755755
756 /* The traffic class in IPv6 is analagous to ToS in IPv4 */
756 /* The traffic class in IPv6 is analogous to ToS in IPv4 */
757757 if (setsockopt(send_socket, IPPROTO_IPV6,
758758 IPV6_TCLASS, &param->type_of_service, sizeof(int))) {
759759 return -1;
3737 #include "timeval.h"
3838 #include "sockaddr.h"
3939
40 char *probe_err;
41
4042 /* Convert the destination address from text to sockaddr */
4143 int decode_address_string(
4244 int ip_version,
9799 {
98100 if (decode_address_string
99101 (param->ip_version, param->remote_address, dest_sockaddr)) {
102 probe_err = "decode address string remote";
100103 return -1;
101104 }
102105
103106 if (param->local_address) {
104107 if (decode_address_string
105108 (param->ip_version, param->local_address, src_sockaddr)) {
106 return -1;
107 }
108 } else {
109 probe_err = "decode address string local";
110 return -1;
111 }
112 } else {
113 probe_err = "find source address";
109114 if (find_source_addr(src_sockaddr, dest_sockaddr)) {
110 return -1;
111 }
115 //probe_err = "find source address";
116 return -1;
117 }
118 probe_err = "";
112119 }
113120 /* DGRAM ICMP id is taken from src_port not from ICMP header */
114121 if (param->protocol == IPPROTO_ICMP) {
310317 int sock;
311318 int len;
312319 struct sockaddr_storage dest_with_port;
320 #ifdef __linux__
321 // The Linux code needs these.
313322 struct sockaddr_in *srcaddr4;
314323 struct sockaddr_in6 *srcaddr6;
324 #endif
325
315326
316327 dest_with_port = *destaddr;
317328
322333 anything to the port.
323334 */
324335 *sockaddr_port_offset(&dest_with_port) = htons(1);
325 len = sockaddr_addr_size(&dest_with_port);
336 len = sockaddr_size(&dest_with_port);
326337
327338 sock = socket(destaddr->ss_family, SOCK_DGRAM, IPPROTO_UDP);
328339 if (sock == -1) {
340 probe_err = "open socket";
329341 return -1;
330342 }
331343
332344 if (connect(sock, (struct sockaddr *) &dest_with_port, len) == 0) {
333345 if (getsockname(sock, (struct sockaddr *) srcaddr, &len)) {
334346 close(sock);
347 probe_err = "getsockname";
335348 return -1;
336349 }
337350 } else {
340353 * a case when mtr is run against unreachable host (that can become
341354 * reachable) */
342355 if (errno != EHOSTUNREACH) {
356 probe_err = "not hostunreach";
343357 close(sock);
344358 return -1;
345359 }
353367 }
354368 #else
355369 close(sock);
370 probe_err = "connect failed";
356371 return -1;
357372 #endif
358373 }
363378 Zero the port, as we may later use this address to finding, and
364379 we don't want to use the port from the socket we just created.
365380 */
366 *sockaddr_port_offset(&srcaddr) = 0;
381 *sockaddr_port_offset(srcaddr) = 0;
367382
368383 return 0;
369384 }
6767 /* The packet "mark" used for mark-based routing on Linux */
6868 int routing_mark;
6969
70 /* Time to live for the transmited probe */
70 /* Time to live for the transmitted probe */
7171 int ttl;
7272
7373 /* The packet size (in bytes) including protocol headers */
206206 struct sockaddr_storage *srcaddr,
207207 const struct sockaddr_storage *destaddr);
208208
209 extern char *probe_err;
210
209211 #endif
8080
8181 We use the Cygwin pipe() to create the pipes, but in the ICMP
8282 service thread we use the Win32 HANDLE that corresponds to the
83 recieving end of the input pipe to wait for ICMP requests.
83 receiving end of the input pipe to wait for ICMP requests.
8484 */
8585
8686
9393 }
9494
9595 /*
96 Convienience similar to error(), but for reporting Windows
96 Convenience similar to error(), but for reporting Windows
9797 error codes instead of errno codes.
9898 */
9999 void error_win(int exit_code, int win_error, const char *str) {
482482 HANDLE event;
483483 BOOL success;
484484 bool read_pending;
485 int read_count;
485 DWORD read_count;
486486 int err;
487487
488488 /*
716716 }
717717
718718 /*
719 On Windows, an implementation of check_probe_timeout is unnecesary because
719 On Windows, an implementation of check_probe_timeout is unnecessary because
720720 timeouts are managed by ICMP.DLL, including a call to the I/O completion
721721 routine when the time fully expires.
722722 */
5151 int packet_size,
5252 const struct sockaddr_storage *sockaddr)
5353 {
54 struct sockaddr_storage dst;
5455 int send_socket = 0;
5556 int sockaddr_length;
57
58 memcpy(&dst, sockaddr, sizeof(struct sockaddr_storage));
5659
5760 if (sockaddr->ss_family == AF_INET6) {
5861 sockaddr_length = sizeof(struct sockaddr_in6);
6669 } else if (param->protocol == IPPROTO_UDP) {
6770 if (net_state->platform.ip6_socket_raw) {
6871 send_socket = net_state->platform.udp6_send_socket;
72 /* we got a ipv6 udp raw socket
73 * the remote port is in the payload
74 * we do not set in the sockaddr
75 */
76 *sockaddr_port_offset(&dst) = 0;
6977 } else {
7078 send_socket = net_state->platform.ip6_txrx_udp_socket;
7179 if (param->dest_port) {
72 *sockaddr_port_offset(sockaddr) = htons(param->dest_port);
80 *sockaddr_port_offset(&dst) = htons(param->dest_port);
7381 } else {
74 *sockaddr_port_offset(sockaddr) = sequence;
82 *sockaddr_port_offset(&dst) = sequence;
7583 }
7684 }
7785 }
9098 } else if (param->protocol == IPPROTO_UDP) {
9199 send_socket = net_state->platform.ip4_txrx_udp_socket;
92100 if (param->dest_port) {
93 *sockaddr_port_offset(sockaddr) = htons(param->dest_port);
101 *sockaddr_port_offset(&dst) = htons(param->dest_port);
94102 } else {
95 *sockaddr_port_offset(sockaddr) = sequence;
103 *sockaddr_port_offset(&dst) = sequence;
96104 }
97105 }
98106 }
104112 }
105113
106114 return sendto(send_socket, packet, packet_size, 0,
107 (struct sockaddr *) sockaddr, sockaddr_length);
115 (struct sockaddr *) &dst, sockaddr_length);
108116 }
109117
110118 /*
144152
145153 if (resolve_probe_addresses(net_state, &param, &p0.remote_addr,
146154 &p0.local_addr)) {
147 fprintf(stderr, "Error decoding localhost address\n");
155 fprintf(stderr, "Error decoding localhost address (%s/%s)\n",
156 probe_err, strerror (errno));
148157 exit(EXIT_FAILURE);
149158 }
150159
682691
683692 /*
684693 Read all available packets through our receiving raw socket, and
685 handle any responses to probes we have preivously sent.
694 handle any responses to probes we have previously sent.
686695 */
687696 static
688697 void receive_replies_from_recv_socket(
794803 memcpy(&remote_addr, SO_EE_OFFENDER(ee), sizeof(remote_addr));
795804 }
796805 }
797 #endif
798806
799807 #ifdef SO_PROTOCOL
800808 if (icmp_connrefused_received) {
814822 packet, packet_length, &timestamp);
815823 } else {
816824 #endif
825 #endif
817826 /* ICMP packets received from raw socket */
818827 handle_received_packet(net_state, &remote_addr, packet,
819828 packet_length, &timestamp);
829 #ifdef HAVE_LINUX_ERRQUEUE_H
820830 #ifdef SO_PROTOCOL
821831 }
832 #endif
822833 #endif
823834 }
824835 }
3939 struct timeval departure_time;
4040 };
4141
42 /* We'll use rack sockets to send and recieve probes on Unix systems */
42 /* We'll use rack sockets to send and receive probes on Unix systems */
4343 struct net_state_platform_t {
4444 /* true if we were successful at opening IPv4 sockets */
4545 bool ip4_present;
1818 #include "wait.h"
1919
2020 #include <error.h>
21 #include <errno.h>
2122 #include <sys/select.h>
2223
2324 #include "command.h"
103103 Sleep until we receive a new probe response, a new command on the
104104 command stream, or a probe timeout. On Unix systems, this means
105105 we use select to wait on file descriptors for the command stream
106 and the raw recieve socket.
106 and the raw receive socket.
107107 */
108108 void wait_for_activity(
109109 struct command_buffer_t *command_buffer,
3333 #define SEQUENCE_NUM 33000
3434
3535 /*
36 Check to see if the packet we've recieved is intended for this test
36 Check to see if the packet we've received is intended for this test
3737 process. We expected the ICMP sequence number to be equal to our
3838 process ID.
3939 */
6161
6262 @unittest.skipIf(sys.platform == 'cygwin', 'No Cygwin test')
6363 class TestIPv6Parameters(mtrpacket.MtrPacketTest):
64 'Test packet paramter customization for IPv6'
64 'Test packet parameter customization for IPv6'
6565
6666 @unittest.skipUnless(mtrpacket.HAVE_IPV6, 'No IPv6')
6767 def test_param(self):
207207 def test_ttl_expired(self):
208208 'Test sending a probe which will have its time-to-live expire'
209209
210 # Probe Goolge's DNS server, but give the probe only one hop
210 # Probe Google's DNS server, but give the probe only one hop
211211 # to live.
212212 self.write_command('16 send-probe ip-4 8.8.8.8 ttl 1')
213213 reply = self.parse_reply()
219219 '''Test sending multiple probes in parallel
220220
221221 We will expect the probes to complete out-of-order by sending
222 a probe to a distant host immeidately followed by a probe to
222 a probe to a distant host immediately followed by a probe to
223223 the local host.'''
224224
225225 success_count = 0
299299 def test_ttl_expired(self):
300300 'Test sending a probe which will have its time-to-live expire'
301301
302 # Probe Goolge's DNS server, but give the probe only one hop
302 # Probe Google's DNS server, but give the probe only one hop
303303 # to live.
304304 cmd = '53 send-probe ip-6 ' + self.google_addr + ' ttl 1'
305305 self.write_command(cmd)
312312 void asn_open(
313313 struct mtr_ctl *ctl)
314314 {
315 if (ctl->ipinfo_no >= 0) {
316 DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
317 if (!(iihash = hcreate(IIHASH_HI)))
318 error(0, errno, "ipinfo hash");
319 }
315 DEB_syslog(LOG_INFO, "hcreate(%d)", IIHASH_HI);
316 if (!(iihash = hcreate(IIHASH_HI)))
317 error(0, errno, "ipinfo hash");
320318 }
321319
322320 void asn_close(
323321 struct mtr_ctl *ctl)
324322 {
325 if ((ctl->ipinfo_no >= 0) && iihash) {
323 if (iihash) {
326324 DEB_syslog(LOG_INFO, "hdestroy()");
327325 hdestroy();
328326 iihash = 0;
7272 struct mtr_ctl *ctl,
7373 struct packet_command_pipe_t *cmdpipe,
7474 const char *cmd,
75 struct command_t *result)
76 {
77 char reply[PACKET_REPLY_BUFFER_SIZE];
75 struct command_t *result,
76 char *reply)
77 {
7878 int command_length;
7979 int write_length;
8080 int read_length;
119119 {
120120 char check_command[COMMAND_BUFFER_SIZE];
121121 struct command_t reply;
122 char reply_buf[PACKET_REPLY_BUFFER_SIZE];
122123
123124 snprintf(check_command, COMMAND_BUFFER_SIZE,
124125 "1 check-support feature %s\n", feature);
125126
126 if (send_synchronous_command(ctl, cmdpipe, check_command, &reply) ==
127 if (send_synchronous_command(ctl, cmdpipe, check_command, &reply, reply_buf) ==
127128 -1) {
128129 return -1;
129130 }
205206
206207 extern char *myname;
207208 /*
208 Execute mtr-packet, allowing the MTR_PACKET evironment to override
209 Execute mtr-packet, allowing the MTR_PACKET environment to override
209210 the PATH when locating the executable.
210211 */
211212 static
753754 /*
754755 Terminate the reply string at the newline, which
755756 is necessary in the case where we are able to read
756 mulitple replies arriving simultaneously.
757 multiple replies arriving simultaneously.
757758 */
758759 *end_of_reply = 0;
759760
423423 addr = net_addr(at);
424424 mpls = net_mpls(at);
425425
426 addrcmp_result = addrcmp(
427 (void *) addr, (void *) &ctl->unspec_addr, ctl->af);
426 addrcmp_result = addrcmp(addr, &ctl->unspec_addr, ctl->af);
428427
429428 if (err == 0 && addrcmp_result != 0) {
430429 name = dns_lookup(ctl, addr);
471470 }
472471
473472 /* Multi path */
474 for (i = 0; i < MAXPATH; i++) {
473 for (i = 0; i < MAX_PATH; i++) {
475474 addrs = net_addrs(at, i);
476475 mplss = net_mplss(at, i);
477 if (addrcmp((void *) addrs, (void *) addr, ctl->af) == 0)
476 if (addrcmp(addrs, addr, ctl->af) == 0)
478477 continue;
479 if (addrcmp
480 ((void *) addrs, (void *) &ctl->unspec_addr,
481 ctl->af) == 0)
478 if (addrcmp(addrs, &ctl->unspec_addr,ctl->af) == 0)
482479 break;
483480
484481 name = dns_lookup(ctl, addrs);
644641 }
645642
646643 if (err == 0
647 && addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
644 && addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
648645
649646 if (!net_up(at)) {
650647 attron(A_BOLD);
700697 pwcenter(buf);
701698 attroff(A_BOLD);
702699
703 mvprintw(1, 0, "%s (%s)", ctl->LocalHostname, net_localaddr());
700 mvprintw(1, 0, "%s (%s) -> %s", ctl->LocalHostname, net_localaddr(), ctl->Hostname);
704701 t = time(NULL);
705702 mvprintw(1, maxx - 25, iso_time(&t));
706703 printw("\n");
8080 case DisplayTXT:
8181 txt_open();
8282 break;
83 #ifdef HAVE_JANSSON
8384 case DisplayJSON:
8485 json_open();
8586 break;
87 #endif
8688 case DisplayXML:
8789 xml_open();
8890 break;
126128 case DisplayTXT:
127129 txt_close(ctl);
128130 break;
131 #ifdef HAVE_JANSSON
129132 case DisplayJSON:
130133 json_close(ctl);
131134 break;
135 #endif
132136 case DisplayXML:
133137 xml_close(ctl);
134138 break;
224228 void display_rawhost(
225229 struct mtr_ctl *ctl,
226230 int host,
227 ip_t * ip_addr)
231 ip_t * ip_addr,
232 struct mplslen *mpls)
228233 {
229234 if (ctl->DisplayMode == DisplayRaw)
230 raw_rawhost(ctl, host, ip_addr);
235 raw_rawhost(ctl, host, ip_addr, mpls);
231236 }
232237
233238
4040 DisplayXML,
4141 DisplayCSV,
4242 DisplayTXT,
43 DisplayJSON
43 #ifdef HAVE_JANSSON
44 DisplayJSON,
45 #endif
4446 };
4547
4648 enum {
7375 extern void display_rawhost(
7476 struct mtr_ctl *ctl,
7577 int hostnum,
76 ip_t * ip_addr);
78 ip_t *ip_addr,
79 struct mplslen *mpls);
7780 extern int display_keyaction(
7881 struct mtr_ctl *ctl);
7982 extern void display_loop(
4040 #include "dns.h"
4141 #include "net.h"
4242 #include "utils.h"
43 #include "packet/sockaddr.h"
4344
4445 struct dns_results {
4546 ip_t ip;
104105 struct dns_results *t;
105106
106107 for (t = results; t; t = t->next) {
107 if (addrcmp((void *) ip, (void *) &t->ip, ctl->af) == 0)
108 if (addrcmp(ip, &t->ip, ctl->af) == 0)
108109 return t;
109110 }
110111
116117 struct sockaddr_storage *sa,
117118 ip_t * ip)
118119 {
119 struct sockaddr_in *sa_in;
120 struct sockaddr_in6 *sa_in6;
121
122120 memset(sa, 0, sizeof(struct sockaddr_storage));
123 switch (ctl->af) {
124 case AF_INET:
125 sa_in = (struct sockaddr_in *) sa;
126 sa_in->sin_family = ctl->af;
127 addrcpy((void *) &sa_in->sin_addr, (void *) ip, ctl->af);
128 break;
129 case AF_INET6:
130 sa_in6 = (struct sockaddr_in6 *) sa;
131 sa_in6->sin6_family = ctl->af;
132 addrcpy((void *) &sa_in6->sin6_addr, (void *) ip, ctl->af);
133 break;
134 }
121 sa->ss_family = ctl->af;
122 memcpy(sockaddr_addr_offset(sa), ip, sockaddr_addr_size(sa));
135123 }
136124
137125 void dns_open(
161149 error(EXIT_FAILURE, errno, "signal");
162150 }
163151
164 /* Close all unneccessary FDs.
152 /* Close all unnecessary FDs.
165153 for debugging and error reporting, keep std-in/out/err. */
166154 for (i = 3; i < fromdns[1]; i++) {
167155 if (i == todns[0])
275263 /* we've got a result. */
276264 if (r->name)
277265 return r->name;
278 else
279 return strlongip(ctl, ip);
280266 } else {
281267 r = xmalloc(sizeof(struct dns_results));
282268 memcpy(&r->ip, ip, sizeof(r->ip));
288274 if (rv < 0)
289275 error(0, errno, "couldn't write to resolver process");
290276 }
291 return strlongip(ctl, ip);
277 return NULL;
292278 }
293279
294280
301287 if (!ctl->dns || !ctl->use_dns)
302288 return NULL;
303289 t = dns_lookup2(ctl, ip);
304 return t;
290 return t ? t : strlongip(ctl, ip);
305291 }
306292
307293 /* XXX check if necessary/exported. */
271271 GtkWidget *Label;
272272 GtkAdjustment *Adjustment;
273273
274 Button = gtk_button_new_from_stock(GTK_STOCK_QUIT);
274 Button = gtk_button_new_with_label("Quit");
275275 gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
276 g_signal_connect(GTK_OBJECT(Button), "clicked",
277 GTK_SIGNAL_FUNC(Window_destroy), NULL);
278
279 Button = gtk_button_new_from_stock(GTK_STOCK_ABOUT);
276 g_signal_connect(G_OBJECT(Button), "clicked",
277 G_CALLBACK(Window_destroy), NULL);
278
279 Button = gtk_button_new_with_label("About");
280280 gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
281 g_signal_connect(GTK_OBJECT(Button), "clicked",
282 GTK_SIGNAL_FUNC(About_clicked), NULL);
281 g_signal_connect(G_OBJECT(Button), "clicked",
282 G_CALLBACK(About_clicked), NULL);
283283
284284 Button = gtk_button_new_with_mnemonic("_Restart");
285285 gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
286 g_signal_connect(GTK_OBJECT(Button), "clicked",
287 GTK_SIGNAL_FUNC(Restart_clicked), ctl);
286 g_signal_connect(G_OBJECT(Button), "clicked",
287 G_CALLBACK(Restart_clicked), ctl);
288288
289289 Pause_Button = gtk_toggle_button_new_with_mnemonic("_Pause");
290290 gtk_box_pack_end(GTK_BOX(Toolbar), Pause_Button, FALSE, FALSE, 0);
291 g_signal_connect(GTK_OBJECT(Pause_Button), "clicked",
292 GTK_SIGNAL_FUNC(Pause_clicked), ctl);
291 g_signal_connect(G_OBJECT(Pause_Button), "clicked",
292 G_CALLBACK(Pause_clicked), ctl);
293293
294294 /* allow root only to set zero delay */
295295 Adjustment = (GtkAdjustment *) gtk_adjustment_new(ctl->WaitTime,
300300 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(Button), TRUE);
301301 gtk_box_pack_end(GTK_BOX(Toolbar), Button, FALSE, FALSE, 0);
302302 ctl->gtk_data = Button;
303 g_signal_connect(GTK_OBJECT(Adjustment), "value_changed",
304 GTK_SIGNAL_FUNC(WaitTime_changed), ctl);
303 g_signal_connect(G_OBJECT(Adjustment), "value_changed",
304 G_CALLBACK(WaitTime_changed), ctl);
305305
306306 Label = gtk_label_new_with_mnemonic("_Hostname:");
307307 gtk_box_pack_start(GTK_BOX(Toolbar), Label, FALSE, FALSE, 0);
308308
309309 Entry = gtk_entry_new();
310310 gtk_entry_set_text(GTK_ENTRY(Entry), ctl->Hostname);
311 g_signal_connect(GTK_OBJECT(Entry), "activate",
312 GTK_SIGNAL_FUNC(Host_activate), ctl);
311 g_signal_connect(G_OBJECT(Entry), "activate",
312 G_CALLBACK(Host_activate), ctl);
313313 gtk_box_pack_start(GTK_BOX(Toolbar), Entry, TRUE, TRUE, 0);
314314
315315 gtk_label_set_mnemonic_widget(GTK_LABEL(Label), Entry);
393393 ReportTreeView =
394394 gtk_tree_view_new_with_model(GTK_TREE_MODEL(ReportStore));
395395
396 g_signal_connect(GTK_OBJECT(ReportTreeView), "button_press_event",
396 g_signal_connect(G_OBJECT(ReportTreeView), "button_press_event",
397397 G_CALLBACK(ReportTreeView_clicked), ctl);
398398
399399 #ifdef HAVE_IPINFO
506506 char str[256] = "???", *name = str;
507507
508508 addr = net_addr(row);
509 if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
509 if (addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
510510 if ((name = dns_lookup(ctl, addr))) {
511511 if (ctl->show_ips) {
512512 snprintf(str, sizeof(str), "%s (%s)", name,
563563 }
564564 }
565565
566 // GTK 3 has changed the interface a bit. Here a few defines so that we can
567 // work with GTK2 or GTK3 as required.
568 #ifdef HAVE_GTK3
569 #define gtk_vbox_new_(orientation,sz) gtk_box_new(orientation, sz)
570 #define gtk_hbox_new_(orientation,sz) gtk_box_new(orientation, sz)
571 #else
572 #define gtk_vbox_new_(orientation,sz) gtk_vbox_new(FALSE, sz)
573 #define gtk_hbox_new_(orientation,sz) gtk_hbox_new(FALSE, sz)
574 #endif
566575
567576 static void Window_fill(
568577 struct mtr_ctl *ctl,
575584 gtk_window_set_title(GTK_WINDOW(Window), "My traceroute");
576585 gtk_window_set_default_size(GTK_WINDOW(Window), 650, 400);
577586 gtk_container_set_border_width(GTK_CONTAINER(Window), 10);
578 VBox = gtk_vbox_new(FALSE, 10);
579
580 Toolbar = gtk_hbox_new(FALSE, 10);
587
588 VBox = gtk_vbox_new_(GTK_ORIENTATION_VERTICAL, 10);
589 Toolbar = gtk_hbox_new_(GTK_ORIENTATION_HORIZONTAL, 10);
590
581591 Toolbar_fill(ctl, Toolbar);
582592 gtk_box_pack_start(GTK_BOX(VBox), Toolbar, FALSE, FALSE, 0);
583593
618628
619629 Window_fill(ctl, main_window);
620630
621 g_signal_connect(GTK_OBJECT(main_window), "delete_event",
622 GTK_SIGNAL_FUNC(Window_destroy), NULL);
623 g_signal_connect(GTK_OBJECT(main_window), "destroy",
624 GTK_SIGNAL_FUNC(Window_destroy), NULL);
631 g_signal_connect(G_OBJECT(main_window), "delete_event",
632 G_CALLBACK(Window_destroy), NULL);
633 g_signal_connect(G_OBJECT(main_window), "destroy",
634 G_CALLBACK(Window_destroy), NULL);
625635
626636 gtk_widget_show_all(main_window);
627637 }
800810 newdestination_item =
801811 gtk_menu_item_new_with_label("Set as new destination");
802812
803 gtk_menu_append(GTK_MENU(popup_menu), copy_item);
804 gtk_menu_append(GTK_MENU(popup_menu), newdestination_item);
805
806 g_signal_connect(GTK_OBJECT(copy_item), "activate",
807 GTK_SIGNAL_FUNC(Copy_activate), path);
813 gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), copy_item);
814 gtk_menu_shell_append(GTK_MENU_SHELL(popup_menu), newdestination_item);
815
816 g_signal_connect(G_OBJECT(copy_item), "activate",
817 G_CALLBACK(Copy_activate), path);
808818
809819 ctl->gtk_data = path;
810 g_signal_connect(GTK_OBJECT(newdestination_item), "activate",
811 GTK_SIGNAL_FUNC(NewDestination_activate), ctl);
820 g_signal_connect(G_OBJECT(newdestination_item), "activate",
821 G_CALLBACK(NewDestination_activate), ctl);
812822
813823 gtk_widget_show(copy_item);
814824 gtk_widget_show(newdestination_item);
815825
826 #ifdef HAVE_GTK3
827 gtk_menu_popup_at_pointer(GTK_MENU(popup_menu), NULL);
828 #else
816829 gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL, NULL, NULL,
817830 0, event->time);
831 #endif
818832 return TRUE;
819833 }
298298 {
299299 int i;
300300
301 memset(ctl->fld_index, -1, FLD_INDEX_SZ);
301 memset(ctl->fld_index, -1, FLD_INDEX_SZ*sizeof(ctl->fld_index[0]));
302302
303303 for (i = 0; data_fields[i].key != 0; i++) {
304304 ctl->available_options[i] = data_fields[i].key;
348348 #endif
349349 {"raw", 0, NULL, 'l'},
350350 {"csv", 0, NULL, 'C'},
351 #ifdef HAVE_JANSSON
351352 {"json", 0, NULL, 'j'},
353 #endif
352354 {"displaymode", 1, NULL, OPT_DISPLAYMODE},
353355 {"split", 0, NULL, 'p'}, /* BL */
354356 /* maybe above should change to -d 'x' */
444446 case 'C':
445447 ctl->DisplayMode = DisplayCSV;
446448 break;
449 #ifdef HAVE_JANSSON
447450 case 'j':
448451 ctl->DisplayMode = DisplayJSON;
449452 break;
453 #endif
450454 case 'x':
451455 ctl->DisplayMode = DisplayXML;
452456 break;
643647
644648 if (ctl->DisplayMode == DisplayReport ||
645649 ctl->DisplayMode == DisplayTXT ||
650 #ifdef HAVE_JANSSON
646651 ctl->DisplayMode == DisplayJSON ||
652 #endif
647653 ctl->DisplayMode == DisplayXML ||
648654 ctl->DisplayMode == DisplayRaw || ctl->DisplayMode == DisplayCSV)
649655 ctl->Interactive = 0;
6060
6161 /* net related definitions */
6262 #define SAVED_PINGS 200
63 #define MAXPATH 8
63 #define MAX_PATH 8
6464 #define MaxHost 256
6565 #define MinPort 1024
6666 #define MaxPort 65535
+122
-218
ui/net.c less more
3838 #include "display.h"
3939 #include "dns.h"
4040 #include "utils.h"
41 #include "packet/sockaddr.h"
4142
4243 #define MinSequence 33000
4344 #define MaxSequence 65536
4445
4546 static int packetsize; /* packet size used by ping */
4647
47 static void sockaddrtop(
48 struct sockaddr *saddr,
49 char *strptr,
50 size_t len);
51
5248 struct nethost {
53 ip_t addr;
54 ip_t addrs[MAXPATH]; /* for multi paths byMin */
49 ip_t addr; /* Latest host to respond */
50 ip_t addrs[MAX_PATH]; /* For Multi paths/Path Changes: List of all hosts that have responded */
5551 int err;
5652 int xmit;
5753 int returned;
7167 int saved[SAVED_PINGS];
7268 int saved_seq_offset;
7369 struct mplslen mpls;
74 struct mplslen mplss[MAXPATH];
70 struct mplslen mplss[MAX_PATH];
7571 };
7672
7773
8783 static struct sequence sequence[MaxSequence];
8884 static struct packet_command_pipe_t packet_command_pipe;
8985
90 #ifdef ENABLE_IPV6
9186 static struct sockaddr_storage sourcesockaddr_struct;
9287 static struct sockaddr_storage remotesockaddr_struct;
93 static struct sockaddr_in6 *ssa6 =
94 (struct sockaddr_in6 *) &sourcesockaddr_struct;
95 static struct sockaddr_in6 *rsa6 =
96 (struct sockaddr_in6 *) &remotesockaddr_struct;
97 #else
98 static struct sockaddr_in sourcesockaddr_struct;
99 static struct sockaddr_in remotesockaddr_struct;
100 #endif
10188
10289 static struct sockaddr *sourcesockaddr =
10390 (struct sockaddr *) &sourcesockaddr_struct;
10491 static struct sockaddr *remotesockaddr =
10592 (struct sockaddr *) &remotesockaddr_struct;
106 static struct sockaddr_in *ssa4 =
107 (struct sockaddr_in *) &sourcesockaddr_struct;
108 static struct sockaddr_in *rsa4 =
109 (struct sockaddr_in *) &remotesockaddr_struct;
11093
11194 static ip_t *sourceaddress;
11295 static ip_t *remoteaddress;
123106 static int batch_at = 0;
124107 static int numhosts = 10;
125108
109
110 #define host_addr_cmp(index, other, af) \
111 addrcmp((void *) &(host[(index)].addr), (void *) (other), (af))
112
113 #define host_addrs_cmp(index, path, other, af) \
114 addrcmp((void *) &(host[(index)].addrs[path]), (void *) (other), (af))
115
116
126117 /* return the number of microseconds to wait before sending the next
127118 ping */
128119 int calc_deltatime(
183174 int time_to_live = index + 1;
184175
185176 send_probe_command(ctl, &packet_command_pipe, remoteaddress,
186 sourceaddress, packetsize, seq, time_to_live);
177 sourceaddress, packet_size, seq, time_to_live);
187178 }
188179
189180
214205
215206 Record the round trip time and address of the responding host.
216207 */
208
217209 static void net_process_ping(
218210 struct mtr_ctl *ctl,
219211 int seq,
226218 int oldavg; /* usedByMin */
227219 int oldjavg; /* usedByMin */
228220 int i; /* usedByMin */
221 int found = 0;
229222 #ifdef ENABLE_IPV6
230223 char addrcopy[sizeof(struct in6_addr)];
231224 #else
232225 char addrcopy[sizeof(struct in_addr)];
233226 #endif
234
235 addrcpy((void *) &addrcopy, (char *) addr, ctl->af);
227 struct nethost *nh = NULL;
228
229 memcpy(&addrcopy, addr, sockaddr_addr_size(sourcesockaddr));
236230
237231 index = mark_sequence_complete(seq);
238232 if (index < 0) {
239233 return;
240234 }
241
242 host[index].err = err;
243
244 if (addrcmp((void *) &(host[index].addr),
245 (void *) &ctl->unspec_addr, ctl->af) == 0) {
246 /* should be out of if as addr can change */
247 addrcpy((void *) &(host[index].addr), addrcopy, ctl->af);
248 host[index].mpls = *mpls;
249 display_rawhost(ctl, index, (void *) &(host[index].addr));
250
251 /* multi paths */
252 addrcpy((void *) &(host[index].addrs[0]), addrcopy, ctl->af);
253 host[index].mplss[0] = *mpls;
254 } else {
255 for (i = 0; i < MAXPATH;) {
256 if (addrcmp
257 ((void *) &(host[index].addrs[i]), (void *) &addrcopy,
258 ctl->af) == 0
259 || addrcmp((void *) &(host[index].addrs[i]),
260 (void *) &ctl->unspec_addr, ctl->af) == 0) {
235 nh = &host[index];
236 nh->err = err;
237
238
239
240 if (addrcmp(&nh->addr, &addrcopy, ctl->af) != 0) {
241 for (i = 0; i < MAX_PATH;) {
242 if (addrcmp(&nh->addrs[i], &nh->addr, ctl->af) == 0) {
243 found = 1; /* This host is already in the list */
261244 break;
245 }
246 if (addrcmp(&nh->addrs[i], &ctl->unspec_addr, ctl->af) == 0) {
247 break; /* Found first vacant position */
262248 }
263249 i++;
264250 }
265251
266 if (addrcmp((void *) &(host[index].addrs[i]), addrcopy, ctl->af) !=
267 0 && i < MAXPATH) {
268 addrcpy((void *) &(host[index].addrs[i]), addrcopy, ctl->af);
269 host[index].mplss[i] = *mpls;
270 display_rawhost(ctl, index, (void *) &(host[index].addrs[i]));
252 if (found == 0 && i < MAX_PATH) {
253 memcpy(&nh->addrs[i], &nh->addr, sockaddr_addr_size(sourcesockaddr));
254
255 nh->mplss[i] = nh->mpls;
256 display_rawhost(ctl, index, (void *)&(nh->addrs[i]), (void *)&(nh->addrs[i]));
271257 }
272 }
273
274 host[index].jitter = totusec - host[index].last;
275 if (host[index].jitter < 0) {
276 host[index].jitter = -host[index].jitter;
277 }
278
279 host[index].last = totusec;
280
281 if (host[index].returned < 1) {
282 host[index].best = host[index].worst = host[index].gmean = totusec;
283 host[index].avg = host[index].ssd = 0;
284
285 host[index].jitter = host[index].jworst = host[index].jinta = 0;
286 }
287
288 if (totusec < host[index].best) {
289 host[index].best = totusec;
290 }
291 if (totusec > host[index].worst) {
292 host[index].worst = totusec;
293 }
294
295 if (host[index].jitter > host[index].jworst) {
296 host[index].jworst = host[index].jitter;
297 }
298
299 host[index].returned++;
300 oldavg = host[index].avg;
301 host[index].avg += (totusec - oldavg + .0) / host[index].returned;
302 host[index].ssd +=
303 (totusec - oldavg + .0) * (totusec - host[index].avg);
304
305 oldjavg = host[index].javg;
306 host[index].javg +=
307 (host[index].jitter - oldjavg) / host[index].returned;
258
259 /* Always save the latest host in nh->addr. This
260 * allows maxTTL to change whenever path changes.
261 */
262 memcpy(&nh->addr, addrcopy, sockaddr_addr_size(sourcesockaddr));
263 nh->mpls = *mpls;
264 display_rawhost(ctl, index, (void *)&(nh->addr), (void *)&(nh->mpls));
265 }
266
267 nh->jitter = totusec - nh->last;
268 if (nh->jitter < 0) {
269 nh->jitter = -nh->jitter;
270 }
271
272 nh->last = totusec;
273
274 if (nh->returned < 1) {
275 nh->best = nh->worst = nh->gmean = totusec;
276 nh->avg = nh->ssd = 0;
277
278 nh->jitter = nh->jworst = nh->jinta = 0;
279 }
280
281 if (totusec < nh->best) {
282 nh->best = totusec;
283 }
284 if (totusec > nh->worst) {
285 nh->worst = totusec;
286 }
287
288 if (nh->jitter > nh->jworst) {
289 nh->jworst = nh->jitter;
290 }
291
292 nh->returned++;
293 oldavg = nh->avg;
294 nh->avg += (totusec - oldavg + .0) / nh->returned;
295 nh->ssd +=
296 (totusec - oldavg + .0) * (totusec - nh->avg);
297
298 oldjavg = nh->javg;
299 nh->javg +=
300 (nh->jitter - oldjavg) / nh->returned;
308301 /* below algorithm is from rfc1889, A.8 */
309 host[index].jinta +=
310 host[index].jitter - ((host[index].jinta + 8) >> 4);
311
312 if (host[index].returned > 1) {
313 host[index].gmean =
314 pow((double) host[index].gmean,
315 (host[index].returned - 1.0) / host[index].returned)
316 * pow((double) totusec, 1.0 / host[index].returned);
317 }
318
319 host[index].sent = 0;
320 host[index].up = 1;
321 host[index].transit = 0;
302 nh->jinta +=
303 nh->jitter - ((nh->jinta + 8) >> 4);
304
305 if (nh->returned > 1) {
306 nh->gmean =
307 pow((double) nh->gmean,
308 (nh->returned - 1.0) / nh->returned)
309 * pow((double) totusec, 1.0 / nh->returned);
310 }
311
312 nh->sent = 0;
313 nh->up = 1;
314 nh->transit = 0;
322315
323316 net_save_return(index, sequence[seq].saved_seq, totusec);
324317 display_rawping(ctl, index, totusec, seq);
474467
475468 max = 0;
476469 for (at = 0; at < ctl->maxTTL; at++) {
477 if (addrcmp((void *) &(host[at].addr),
478 (void *) remoteaddress, ctl->af) == 0) {
470 if (host_addr_cmp(at , remoteaddress, ctl->af) == 0) {
479471 return at + 1;
480472 } else if (host[at].err != 0) {
481473 /*
484476 final hop.
485477 */
486478 return at + 1;
487 } else if (addrcmp((void *) &(host[at].addr),
488 (void *) &ctl->unspec_addr, ctl->af) != 0) {
479 } else if (host_addr_cmp(at, &ctl->unspec_addr, ctl->af) != 0) {
489480 max = at + 2;
490481 }
491482 }
545536 struct mtr_ctl *ctl)
546537 {
547538 int n_unknown = 0, i;
539 int restart = 0;
548540
549541 /* randomized packet size and/or bit pattern if packetsize<0 and/or
550542 bitpattern<0. abs(packetsize) and/or abs(bitpattern) will be used
556548 have a range for "rand()" that runs to 32768, and the
557549 destination range is 10000, you end up with 4 out of 32768
558550 0-2768's and only 3 out of 32768 for results 2769 .. 9999.
559 As our detination range (in the example 10000) is much
551 As our destination range (in the example 10000) is much
560552 smaller (reasonable packet sizes), and our rand() range much
561553 larger, this effect is insignificant. Oh! That other formula
562554 didn't work. */
574566 net_send_query(ctl, batch_at, abs(packetsize));
575567
576568 for (i = ctl->fstTTL - 1; i < batch_at; i++) {
577 if (addrcmp
578 ((void *) &(host[i].addr), (void *) &ctl->unspec_addr,
579 ctl->af) == 0)
569 if (host_addr_cmp(i, &ctl->unspec_addr, ctl->af) == 0)
580570 n_unknown++;
581571
582572 /* The second condition in the next "if" statement was added in mtr-0.56,
584574 hosts. Removed in 0.65.
585575 If the line proves necessary, it should at least NOT trigger that line
586576 when host[i].addr == 0 */
587 if ((addrcmp((void *) &(host[i].addr),
588 (void *) remoteaddress, ctl->af) == 0))
589 n_unknown = MaxHost; /* Make sure we drop into "we should restart" */
577 if (host_addr_cmp(i, remoteaddress, ctl->af) == 0) {
578 restart = 1;
579 numhosts = i + 1; /* Saves batch_at - index number of probes in the next round!*/
580 break;
581 }
590582 }
591583
592584 if ( /* success in reaching target */
593 (addrcmp((void *) &(host[batch_at].addr),
594 (void *) remoteaddress, ctl->af) == 0) ||
585 (host_addr_cmp(batch_at, remoteaddress, ctl->af) == 0) ||
595586 /* fail in consecutive maxUnknown (firewall?) */
596587 (n_unknown > ctl->maxUnknown) ||
597588 /* or reach limit */
598589 (batch_at >= ctl->maxTTL - 1)) {
590 restart = 1;
599591 numhosts = batch_at + 1;
592 }
593
594 if(restart) {
600595 batch_at = ctl->fstTTL - 1;
601596 return 1;
602597 }
643638
644639 interface = ifaddrs;
645640 while (interface != NULL) {
646 if (!strcmp(interface->ifa_name, interface_name)) {
641 if (interface->ifa_addr != NULL && !strcmp(interface->ifa_name, interface_name)) {
647642 found_interface_name = 1;
648643
649644 if (interface->ifa_addr->sa_family == address_family) {
689684 int udp_socket;
690685 int addr_length;
691686 struct sockaddr_storage remote_sockaddr;
692 struct sockaddr_in *remote4;
693 struct sockaddr_in6 *remote6;
694687
695688 udp_socket =
696689 socket(remotesockaddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
702695 We need to set the port to a non-zero value for the connect
703696 to succeed.
704697 */
705 if (remotesockaddr->sa_family == AF_INET6) {
706 #ifdef ENABLE_IPV6
707 addr_length = sizeof(struct sockaddr_in6);
708
709 memcpy(&remote_sockaddr, rsa6, addr_length);
710 remote6 = (struct sockaddr_in6 *) &remote_sockaddr;
711 remote6->sin6_port = htons(1);
712 #endif
713 } else {
714 addr_length = sizeof(struct sockaddr_in);
715
716 memcpy(&remote_sockaddr, rsa4, addr_length);
717 remote4 = (struct sockaddr_in *) &remote_sockaddr;
718 remote4->sin_port = htons(1);
719 }
698 addr_length = sockaddr_size(&remotesockaddr_struct);
699 memcpy(&remote_sockaddr, &remotesockaddr_struct, addr_length);
700 *sockaddr_port_offset(&remote_sockaddr) = htons(1);
720701
721702 if (connect
722 (udp_socket, (struct sockaddr *) &remote_sockaddr, addr_length)) {
703 (udp_socket, (struct sockaddr *) &remote_sockaddr, sockaddr_size(&remote_sockaddr))) {
723704 #ifdef __linux__
724705 /* Linux doesn't require source address, so we can support
725706 * a case when mtr is run against unreachable host (that can become
738719 error(EXIT_FAILURE, errno, "local address determination failed");
739720 }
740721
741 sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
722 inet_ntop(sourcesockaddr->sa_family, sockaddr_addr_offset(sourcesockaddr), localaddr, sizeof(localaddr));
742723
743724 close(udp_socket);
744725 }
758739
759740 net_reset(ctl);
760741
761 remotesockaddr->sa_family = hostent->h_addrtype;
762
763 switch (hostent->h_addrtype) {
764 case AF_INET:
765 addrcpy((void *) &(rsa4->sin_addr), hostent->h_addr, AF_INET);
766 sourceaddress = (ip_t *) & (ssa4->sin_addr);
767 remoteaddress = (ip_t *) & (rsa4->sin_addr);
768 break;
769 #ifdef ENABLE_IPV6
770 case AF_INET6:
771 addrcpy((void *) &(rsa6->sin6_addr), hostent->h_addr, AF_INET6);
772 sourceaddress = (ip_t *) & (ssa6->sin6_addr);
773 remoteaddress = (ip_t *) & (rsa6->sin6_addr);
774 break;
775 #endif
776 default:
777 error(EXIT_FAILURE, 0, "net_open bad address type");
778 }
742 remotesockaddr->sa_family = sourcesockaddr->sa_family = hostent->h_addrtype;
743 memcpy(sockaddr_addr_offset(remotesockaddr), hostent->h_addr, sockaddr_addr_size(remotesockaddr));
744
745 sourceaddress = sockaddr_addr_offset(sourcesockaddr);
746 remoteaddress = sockaddr_addr_offset(remotesockaddr);
779747
780748 if (ctl->InterfaceAddress) {
781749 net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
782750 } else if (ctl->InterfaceName) {
783751 net_find_interface_address_from_name(
784752 &sourcesockaddr_struct, ctl->af, ctl->InterfaceName);
785
786 sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
753 inet_ntop(sourcesockaddr->sa_family, sockaddr_addr_offset(sourcesockaddr), localaddr, sizeof(localaddr));
787754 } else {
788755 net_find_local_address();
789756 }
803770 }
804771
805772 remotesockaddr->sa_family = addr->h_addrtype;
806 addrcpy((void *) remoteaddress, addr->h_addr, addr->h_addrtype);
807
808 switch (addr->h_addrtype) {
809 case AF_INET:
810 addrcpy((void *) &(rsa4->sin_addr), addr->h_addr, AF_INET);
811 break;
812 #ifdef ENABLE_IPV6
813 case AF_INET6:
814 addrcpy((void *) &(rsa6->sin6_addr), addr->h_addr, AF_INET6);
815 break;
816 #endif
817 default:
818 error(EXIT_FAILURE, 0, "net_reopen bad address type");
819 }
820
773 memcpy(remoteaddress, addr->h_addr, sockaddr_addr_size(remotesockaddr));
774 memcpy(sockaddr_addr_offset(remotesockaddr), addr->h_addr, sockaddr_addr_size(remotesockaddr));
821775 net_reset(ctl);
822776 net_send_batch(ctl);
823777 }
906860 host[at].saved[idx] = ms;
907861 }
908862
909 /* Similar to inet_ntop but uses a sockaddr as it's argument. */
910 static void sockaddrtop(
911 struct sockaddr *saddr,
912 char *strptr,
913 size_t len)
914 {
915 struct sockaddr_in *sa4;
916 #ifdef ENABLE_IPV6
917 struct sockaddr_in6 *sa6;
918 #endif
919
920 switch (saddr->sa_family) {
921 case AF_INET:
922 sa4 = (struct sockaddr_in *) saddr;
923 xstrncpy(strptr, inet_ntoa(sa4->sin_addr), len - 1);
924 strptr[len - 1] = '\0';
925 return;
926 #ifdef ENABLE_IPV6
927 case AF_INET6:
928 sa6 = (struct sockaddr_in6 *) saddr;
929 inet_ntop(sa6->sin6_family, &(sa6->sin6_addr), strptr, len);
930 return;
931 #endif
932 default:
933 error(0, 0, "sockaddrtop unknown address type");
934 strptr[0] = '\0';
935 return;
936 }
937 }
938
939
940863 /* Address comparison. */
941864 int addrcmp(
942 char *a,
943 char *b,
865 void *a,
866 void *b,
944867 int family)
945868 {
946869 int rc = -1;
959882 return rc;
960883 }
961884
962 /* Address copy. */
963 void addrcpy(
964 char *a,
965 char *b,
966 int family)
967 {
968
969 switch (family) {
970 case AF_INET:
971 memcpy(a, b, sizeof(struct in_addr));
972 break;
973 #ifdef ENABLE_IPV6
974 case AF_INET6:
975 memcpy(a, b, sizeof(struct in6_addr));
976 break;
977 #endif
978 }
979 }
980
981885 /* for GTK frontend */
982886 void net_harvest_fds(
983887 struct mtr_ctl *ctl)
116116 int ms);
117117
118118 extern int addrcmp(
119 char *a,
120 char *b,
121 int af);
122 extern void addrcpy(
123 char *a,
124 char *b,
119 void *a,
120 void *b,
125121 int af);
126122
127123 extern void net_add_fds(
6363 fflush(stdout);
6464 }
6565
66
6766 void raw_rawhost(
6867 struct mtr_ctl *ctl,
6968 int host,
70 ip_t * ip_addr)
69 ip_t *ip_addr,
70 struct mplslen *mpls)
7171 {
7272 printf("h %d %s\n", host, strlongip(ctl, ip_addr));
73 if (ctl->enablempls) {
74 int k;
75 for (k = 0; k < mpls->labels; k++)
76 printf("m %d %lu %u %u %u\n",
77 host, mpls->label[k], mpls->tc[k], mpls->s[k], mpls->ttl[k]);
78 }
79
7380 fflush(stdout);
7481 }
2929 extern void raw_rawhost(
3030 struct mtr_ctl *ctl,
3131 int host,
32 ip_t * addr);
32 ip_t *addr,
33 struct mplslen *mpls);
2525 #include <string.h>
2626 #include <strings.h>
2727 #include <time.h>
28 #ifdef HAVE_JANSSON
29 #include <jansson.h>
30 #endif
31 #ifdef HAVE_ERROR_H
32 #include <error.h>
33 #else
34 #include "portability/error.h"
35 #endif
2836
2937 #include "mtr.h"
3038 #include "report.h"
175183
176184 /* This feature shows 'loadbalances' on routes */
177185
178 /* z is starting at 1 because addrs[0] is the same that addr */
179 for (z = 1; z < MAXPATH; z++) {
186 /* Print list of all hosts that have responded from ttl = at + 1 away */
187 for (z = 0; z < MAX_PATH; z++) {
180188 int found = 0;
181189 addr2 = net_addrs(at, z);
182190 mplss = net_mplss(at, z);
183191 if ((addrcmp
184192 ((void *) &ctl->unspec_addr, (void *) addr2,
185 ctl->af)) == 0)
193 ctl->af)) == 0) {
186194 break;
195 } else if ((addrcmp
196 ((void *) addr, (void *) addr2,
197 ctl->af)) == 0) {
198 continue; /* Latest Host is already printed */
199 } else {
200 snprint_addr(ctl, name, sizeof(name), addr2);
201 snprintf(fmt, sizeof(fmt), " %%-%zus", len_hosts);
202 snprintf(buf, sizeof(buf), fmt, name);
203 printf("%s\n", buf);
204 }
187205 for (w = 0; w < z; w++)
188206 /* Ok... checking if there are ips repeated on same hop */
189207 if ((addrcmp
268286 report_close(ctl);
269287 }
270288
271
289 #ifdef HAVE_JANSSON
272290 void json_open(
273291 void)
274292 {
275293 }
276294
277
278 void json_close(
279 struct mtr_ctl *ctl)
280 {
281 int i, j, at, first, max;
295 void json_close(struct mtr_ctl *ctl)
296 {
297 int i, j, at, max;
298 int ret;
299 char buf[128];
300 json_t *jreport, *jmtr, *jhubs, *jh;
282301 ip_t *addr;
283302 char name[MAX_FORMAT_STR];
284303
285 printf("{\n");
286 printf(" \"report\": {\n");
287 printf(" \"mtr\": {\n");
288 printf(" \"src\": \"%s\",\n", ctl->LocalHostname);
289 printf(" \"dst\": \"%s\",\n", ctl->Hostname);
290 printf(" \"tos\": \"0x%X\",\n", ctl->tos);
304 jmtr = json_pack("{ss ss si si}",
305 "src", ctl->LocalHostname,
306 "dst", ctl->Hostname,
307 "tos", ctl->tos,
308 "tests", ctl->MaxPing);
309 if (!jmtr)
310 goto on_error;
311
291312 if (ctl->cpacketsize >= 0) {
292 printf(" \"psize\": \"%d\",\n", ctl->cpacketsize);
313 snprintf(buf, sizeof(buf), "%d", ctl->cpacketsize);
293314 } else {
294 printf(" \"psize\": \"rand(%d-%d)\",\n", MINPACKET,
295 -ctl->cpacketsize);
296 }
315 snprintf(buf, sizeof(buf), "rand(%d-%d)", MINPACKET, -ctl->cpacketsize);
316 }
317 ret = json_object_set_new(jmtr, "psize", json_string(buf));
318 if (ret == -1)
319 goto on_error;
320
297321 if (ctl->bitpattern >= 0) {
298 printf(" \"bitpattern\": \"0x%02X\",\n",
299 (unsigned char) (ctl->bitpattern));
322 snprintf(buf, sizeof(buf), "0x%02X", (unsigned char)(ctl->bitpattern));
300323 } else {
301 printf(" \"bitpattern\": \"rand(0x00-FF)\",\n");
302 }
303 printf(" \"tests\": \"%d\"\n", ctl->MaxPing);
304 printf(" },\n");
305
306 printf(" \"hubs\": [");
324 snprintf(buf, sizeof(buf), "rand(0x00-FF)");
325 }
326
327 ret = json_object_set_new(jmtr, "bitpattern", json_string(buf));
328 if (ret == -1)
329 goto on_error;
330
331 jhubs = json_array();
332 if (!jhubs)
333 goto on_error;
307334
308335 max = net_max(ctl);
309 at = first = net_min(ctl);
336 at = net_min(ctl);
310337 for (; at < max; at++) {
311338 addr = net_addr(at);
312339 snprint_addr(ctl, name, sizeof(name), addr);
313340
314 if (at == first) {
315 printf("{\n");
316 } else {
317 printf(" {\n");
318 }
319 printf(" \"count\": \"%d\",\n", at + 1);
320 printf(" \"host\": \"%s\",\n", name);
341 jh = json_pack("{si ss}", "count", at + 1, "host", name);
342 if (!jh)
343 goto on_error;
344
321345 #ifdef HAVE_IPINFO
322346 if(!ctl->ipinfo_no) {
323 char* fmtinfo = fmt_ipinfo(ctl, addr);
324 if (fmtinfo != NULL) fmtinfo = trim(fmtinfo, '\0');
325 printf(" \"ASN\": \"%s\",\n", fmtinfo);
326 }
327 #endif
347 char* fmtinfo = fmt_ipinfo(ctl, addr);
348 if (fmtinfo != NULL)
349 fmtinfo = trim(fmtinfo, '\0');
350
351 ret = json_object_set_new(jh, "ASN", json_string(fmtinfo));
352 if (ret == -1)
353 goto on_error;
354 }
355 #endif
356
328357 for (i = 0; i < MAXFLD; i++) {
329 const char *format;
330
331358 j = ctl->fld_index[ctl->fld_active[i]];
332359
333 /* Commas */
334 if (i + 1 == MAXFLD) {
335 printf("\n");
336 } else if (j > 0 && i != 0) {
337 printf(",\n");
338 }
339
340360 if (j <= 0)
341 continue; /* Field nr 0, " " shouldn't be printed in this method. */
342
343 /* Format value */
344 format = data_fields[j].format;
345 if (strchr(format, 'f')) {
346 format = "%.2f";
361 continue; /* Field nr 0, " " shouldn't be printed in this method. */
362
363 if (strchr(data_fields[j].format, 'f')) {
364 ret = json_object_set_new(
365 jh, data_fields[j].title,
366 json_real(data_fields[j].net_xxx(at) / 1000.0));
347367 } else {
348 format = "%d";
349 }
350
351 /* Format json line */
352 snprintf(name, sizeof(name), "%s%s", " \"%s\": ", format);
353
354 /* Output json line */
355 if (strchr(data_fields[j].format, 'f')) {
356 /* 1000.0 is a temporay hack for stats usec to ms, impacted net_loss. */
357 printf(name,
358 data_fields[j].title,
359 data_fields[j].net_xxx(at) / 1000.0);
360 } else {
361 printf(name,
362 data_fields[j].title, data_fields[j].net_xxx(at));
363 }
364 }
365 if (at + 1 == max) {
366 printf(" }");
367 } else {
368 printf(" },\n");
369 }
370 }
371 printf("]\n");
372 printf(" }\n");
373 printf("}\n");
374 }
375
368 ret = json_object_set_new(
369 jh, data_fields[j].title,
370 json_integer(data_fields[j].net_xxx(at)));
371 }
372 if (ret == -1)
373 goto on_error;
374 }
375
376 ret = json_array_append_new(jhubs, jh);
377 if (ret == -1)
378 goto on_error;
379 }
380
381 jreport = json_pack("{s{so so}}", "report", "mtr", jmtr, "hubs", jhubs);
382
383 ret = json_dumpf(jreport, stdout, JSON_INDENT(4) | JSON_REAL_PRECISION(5));
384 if (ret == -1)
385 goto on_error;
386
387 printf("\n"); // bash promt should be on new line
388 json_decref(jreport);
389 return;
390 on_error:
391 error(EXIT_FAILURE, 0, "json_close failed");
392 }
393 #endif
376394
377395
378396 void xml_open(
9191 */
9292 for (at = 0; at < max; at++) {
9393 addr = net_addr(at);
94 if (addrcmp((void *) addr, (void *) &ctl->unspec_addr, ctl->af)) {
94 if (addrcmp(addr, &ctl->unspec_addr, ctl->af)) {
9595 char str[256], *name;
9696 if (!(name = dns_lookup(ctl, addr)))
9797 name = strlongip(ctl, addr);