char *command,
int buffer_size,
int command_token,
- ip_t *address)
+ ip_t *address,
+ ip_t *localaddress)
{
char ip_string[INET6_ADDRSTRLEN];
+ char local_ip_string[INET6_ADDRSTRLEN];
const char *ip_type;
+ const char *local_ip_type;
const char *protocol = NULL;
/* Conver the remote IP address to a string */
if (inet_ntop(
- ctl->af, address, ip_string, INET6_ADDRSTRLEN) == NULL) {
+ ctl->af, address,
+ ip_string, INET6_ADDRSTRLEN) == NULL) {
display_close(ctl);
- error(EXIT_FAILURE, errno, "failure stringifying remote IP address");
+ error(EXIT_FAILURE, errno, "invalid remote IP address");
+ }
+
+ if (inet_ntop(
+ ctl->af, localaddress,
+ local_ip_string, INET6_ADDRSTRLEN) == NULL) {
+
+ display_close(ctl);
+ error(EXIT_FAILURE, errno, "invalid local IP address");
}
if (ctl->af == AF_INET6) {
ip_type = "ip-6";
+ local_ip_type = "local-ip-6";
} else {
ip_type = "ip-4";
+ local_ip_type = "local-ip-4";
}
if (ctl->mtrtype == IPPROTO_ICMP) {
snprintf(
command, buffer_size,
- "%d send-probe %s %s protocol %s",
- command_token, ip_type, ip_string, protocol);
+ "%d send-probe %s %s %s %s protocol %s",
+ command_token,
+ ip_type, ip_string, local_ip_type, local_ip_string,
+ protocol);
}
struct mtr_ctl *ctl,
struct packet_command_pipe_t *cmdpipe,
ip_t *address,
+ ip_t *localaddress,
int packet_size,
int sequence,
int time_to_live)
{
char command[COMMAND_BUFFER_SIZE];
int remaining_size;
+ int timeout;
construct_base_command(
- ctl, command, COMMAND_BUFFER_SIZE, sequence, address);
+ ctl, command, COMMAND_BUFFER_SIZE, sequence, address, localaddress);
append_command_argument(
command, COMMAND_BUFFER_SIZE, "size", packet_size);
append_command_argument(
- command, COMMAND_BUFFER_SIZE, "bitpattern", ctl->bitpattern);
+ command, COMMAND_BUFFER_SIZE, "bit-pattern", ctl->bitpattern);
append_command_argument(
command, COMMAND_BUFFER_SIZE, "tos", ctl->tos);
append_command_argument(
command, COMMAND_BUFFER_SIZE, "ttl", time_to_live);
+ timeout = ctl->probe_timeout / 1000000;
+ append_command_argument(
+ command, COMMAND_BUFFER_SIZE, "timeout", timeout);
+
if (ctl->remoteport) {
append_command_argument(
command, COMMAND_BUFFER_SIZE, "port", ctl->remoteport);
if (ctl->localport) {
append_command_argument(
- command, COMMAND_BUFFER_SIZE, "localport", ctl->localport);
+ command, COMMAND_BUFFER_SIZE, "local-port", ctl->localport);
}
#ifdef SO_MARK
error(EXIT_FAILURE, 0, "Permission denied");
}
+ if (!strcmp(reply_name, "address-in-use")) {
+ display_close(ctl);
+ error(EXIT_FAILURE, 0, "Address in use");
+ }
+
+ if (!strcmp(reply_name, "address-not-available")) {
+ display_close(ctl);
+ error(EXIT_FAILURE, 0, "Address not available");
+ }
+
if (!strcmp(reply_name, "unexpected-error")) {
display_close(ctl);
error(EXIT_FAILURE, 0, "Unexpected mtr-packet error");
struct mtr_ctl *ctl,
struct packet_command_pipe_t *cmdpipe,
ip_t *address,
+ ip_t *localaddress,
int packet_size,
int sequence,
int time_to_live);
probes.
.HP 7
.IP
-.B localport
+.B local-ip-4
+.I IP-ADDRESS
+.HP 14
+.IP
+The local Internet Procol version 4 address to use when sending probes.
+.HP 7
+.IP
+.B local-ip-6
+.I IP-ADDRESS
+.HP 14
+.IP
+The local Internet Protocol version 6 address to use when sending probes.
+.HP 7
+.IP
+.B local-port
.I PORT-NUMBER
.HP 14
.IP
Internet Protocol header and transport protocol header.
.HP 7
.IP
-.B bitpattern
+.B bit-pattern
.I PATTERN-VALUE
.HP 14
.IP
The source port number for UDP traces.
.TP
.B \-Z \fISECONDS\fR, \fB\-\-timeout \fISECONDS
-The number of seconds to keep the TCP socket open before giving up on
-the connection. This will only affect the final hop. Using large values
-for this, especially combined with a short interval, will use up a lot
-of file descriptors.
+The number of seconds to keep probe sockets open before giving up on
+the connection. Using large values for this, especially combined with
+a short interval, will use up a lot of file descriptors.
.TP
.B \-M \fIMARK\fR, \fB\-\-mark \fIMARK
Set the mark for each packet sent through this socket similar to the
fputs(" -F, --filename FILE read hostname(s) from a file\n", out);
fputs(" -4 use IPv4 only\n", out);
fputs(" -6 use IPv6 only\n", out);
- fputs(" -u, --udp use udp instead of icmp echo\n", out);
- fputs(" -T, --tcp use tcp instead of icmp echo\n", out);
+ fputs(" -u, --udp use UDP instead of ICMP echo\n", out);
+ fputs(" -T, --tcp use TCP instead of ICMP echo\n", out);
fputs(" -a, --address ADDRESS bind the outgoing socket to ADDRESS\n", out);
fputs(" -f, --first-ttl NUMBER set what TTL to start\n", out);
fputs(" -m, --max-ttl NUMBER maximum number of hops\n", out);
fputs(" -U, --max-unknown NUMBER maximum unknown host\n", out);
- fputs(" -P, --port PORT target port number for tcp, sctp, or udp\n", out);
- fputs(" -L, --localport LOCALPORT source port number for udp\n", out);
+ fputs(" -P, --port PORT target port number for TCP, SCTP, or UDP\n", out);
+ fputs(" -L, --localport LOCALPORT source port number for UDP\n", out);
fputs(" -s, --psize PACKETSIZE set the packet size used for probing\n", out);
fputs(" -B, --bitpattern NUMBER set bit pattern to use in payload\n", out);
- fputs(" -i, --interval SECONDS icmp echo request interval\n", out);
+ fputs(" -i, --interval SECONDS ICMP echo request interval\n", out);
fputs(" -G, --gracetime SECONDS number of seconds to wait for responses\n", out);
fputs(" -Q, --tos NUMBER type of service field in IP header\n", out);
fputs(" -e, --mpls display information from ICMP extensions\n", out);
- fputs(" -Z, --timeout SECONDS seconds to keep the TCP socket open\n", out);
+ fputs(" -Z, --timeout SECONDS seconds to keep probe sockets open\n", out);
fputs(" -M, --mark MARK mark each sent packet\n", out);
fputs(" -r, --report output using report mode\n", out);
fputs(" -w, --report-wide output wide report\n", out);
fputs(" -b, --show-ips show IP numbers and host names\n", out);
fputs(" -o, --order FIELDS select output fields\n", out);
#ifdef HAVE_IPINFO
- fputs(" -y, --ipinfo NUMBER select ip information in output\n", out);
+ fputs(" -y, --ipinfo NUMBER select IP information in output\n", out);
fputs(" -z, --aslookup display AS number\n", out);
#endif
fputs(" -h, --help display this help and exit\n", out);
{ "sctp", 0, NULL, 'S' }, /* SCTP (default is ICMP) */
{ "port", 1, NULL, 'P' }, /* target port number for TCP/SCTP/UDP */
{ "localport", 1, NULL, 'L' }, /* source port number for UDP */
- { "timeout", 1, NULL, 'Z' }, /* timeout for TCP sockets */
+ { "timeout", 1, NULL, 'Z' }, /* timeout for probe sockets */
{ "gracetime", 1, NULL, 'G' }, /* gracetime for replies after last probe */
#ifdef SO_MARK
{ "mark", 1, NULL, 'M' }, /* use SO_MARK */
}
break;
case 'Z':
- ctl->tcp_timeout = strtonum_or_err(optarg, "invalid argument", STRTO_INT);
- ctl->tcp_timeout *= 1000000;
+ ctl->probe_timeout = strtonum_or_err(optarg, "invalid argument", STRTO_INT);
+ ctl->probe_timeout *= 1000000;
break;
case '4':
ctl->af = AF_INET;
ctl.fstTTL = 1;
ctl.maxTTL = 30;
ctl.maxUnknown = 12;
- ctl.tcp_timeout = 10 * 1000000;
+ ctl.probe_timeout = 10 * 1000000;
ctl.ipinfo_no = -1;
ctl.ipinfo_max = -1;
xstrncpy(ctl.fld_active, "LS NABWV", 2 * MAXFLD);
int maxUnknown; /* stop ping threshold */
int remoteport; /* target port for TCP tracing */
int localport; /* source port for UDP tracing */
- int tcp_timeout; /* timeout for TCP connections */
+ int probe_timeout; /* timeout for probe sockets */
unsigned char fld_active[2 * MAXFLD]; /* SO_MARK to set for ping packet*/
int display_mode; /* display mode selector */
int fld_index[FLD_INDEX_SZ]; /* default display field (defined by key in net.h) and order */
#include "config.h"
+#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <sys/select.h>
+#include <unistd.h>
#ifdef HAVE_ERROR_H
# include <error.h>
static int packetsize; /* packet size used by ping */
+static void sockaddrtop( struct sockaddr * saddr, char * strptr, size_t len );
+
struct nethost {
ip_t addr;
ip_t addrs[MAXPATH]; /* for multi paths byMin */
static struct sockaddr_in remotesockaddr_struct;
#endif
+static struct sockaddr * sourcesockaddr = (struct sockaddr *) &sourcesockaddr_struct;
static struct sockaddr * remotesockaddr = (struct sockaddr *) &remotesockaddr_struct;
static struct sockaddr_in * ssa4 = (struct sockaddr_in *) &sourcesockaddr_struct;
static struct sockaddr_in * rsa4 = (struct sockaddr_in *) &remotesockaddr_struct;
int time_to_live = index + 1;
send_probe_command(
- ctl, &packet_command_pipe, remoteaddress, packetsize, seq, time_to_live);
+ ctl, &packet_command_pipe, remoteaddress, sourceaddress,
+ packetsize, seq, time_to_live);
}
}
+/* Ensure the interface address a valid address for our use */
+static void net_validate_interface_address(
+ int address_family, char *interface_address)
+{
+ if (inet_pton(
+ address_family, interface_address, sourceaddress) != 1) {
+
+ error(EXIT_FAILURE, errno, "invalid local address");
+ }
+
+ if (inet_ntop(
+ address_family, sourceaddress, localaddr, sizeof(localaddr)) == NULL) {
+
+ error(EXIT_FAILURE, errno, "invalid local address");
+ }
+}
+
+
+/*
+ Find the local address we will use to sent to the remote
+ host by connecting a UDP socket and checking the address
+ the socket is bound to.
+*/
+static void net_find_local_address(void)
+{
+ int udp_socket;
+ int addr_length;
+ struct sockaddr_storage remote_sockaddr;
+ struct sockaddr_in *remote4;
+ struct sockaddr_in6 *remote6;
+
+ udp_socket = socket(remotesockaddr->sa_family, SOCK_DGRAM, IPPROTO_UDP);
+ if (udp_socket == -1) {
+ error(EXIT_FAILURE, errno, "udp socket creation failed");
+ }
+
+ /*
+ We need to set the port to a non-zero value for the connect
+ to succeed.
+ */
+ if (remotesockaddr->sa_family == AF_INET6) {
+ addr_length = sizeof(struct sockaddr_in6);
+
+ memcpy(&remote_sockaddr, rsa6, addr_length);
+ remote6 = (struct sockaddr_in6 *)&remote_sockaddr;
+ remote6->sin6_port = htons(1);
+ } else {
+ addr_length = sizeof(struct sockaddr_in);
+
+ memcpy(&remote_sockaddr, rsa4, addr_length);
+ remote4 = (struct sockaddr_in *)&remote_sockaddr;
+ remote4->sin_port = htons(1);
+ }
+
+ if (connect(udp_socket, (struct sockaddr *)&remote_sockaddr, addr_length)) {
+ error(EXIT_FAILURE, errno, "udp socket connect failed");
+ }
+
+ if (getsockname(udp_socket, sourcesockaddr, &addr_length)) {
+
+ error(EXIT_FAILURE, errno, "local address determination failed");
+ }
+
+ sockaddrtop(sourcesockaddr, localaddr, sizeof(localaddr));
+
+ close(udp_socket);
+}
+
+
extern int net_open(struct mtr_ctl *ctl, struct hostent * hostent)
{
int err;
error(EXIT_FAILURE, 0, "net_open bad address type");
}
+ if (ctl->InterfaceAddress) {
+ net_validate_interface_address(ctl->af, ctl->InterfaceAddress);
+ } else {
+ net_find_local_address();
+ }
+
return 0;
}
host[at].saved[idx] = ms;
}
+/* Similar to inet_ntop but uses a sockaddr as it's argument. */
+static void sockaddrtop( struct sockaddr * saddr, char * strptr, size_t len ) {
+ struct sockaddr_in * sa4;
+#ifdef ENABLE_IPV6
+ struct sockaddr_in6 * sa6;
+#endif
+
+ switch ( saddr->sa_family ) {
+ case AF_INET:
+ sa4 = (struct sockaddr_in *) saddr;
+ xstrncpy( strptr, inet_ntoa( sa4->sin_addr ), len - 1 );
+ strptr[ len - 1 ] = '\0';
+ return;
+#ifdef ENABLE_IPV6
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *) saddr;
+ inet_ntop( sa6->sin6_family, &(sa6->sin6_addr), strptr, len );
+ return;
+#endif
+ default:
+ error(0, 0, "sockaddrtop unknown address type");
+ strptr[0] = '\0';
+ return;
+ }
+}
+
+
/* Address comparison. */
extern int addrcmp( char * a, char * b, int family ) {
int rc = -1;
/* Pass IPv4 addresses as string values */
if (!strcmp(name, "ip-4")) {
param->ip_version = 4;
- param->address = value;
+ param->remote_address = value;
}
/* IPv6 address */
if (!strcmp(name, "ip-6")) {
param->ip_version = 6;
- param->address = value;
+ param->remote_address = value;
+ }
+
+ /* IPv4 address to send from */
+ if (!strcmp(name, "local-ip-4")) {
+ param->local_address = value;
+ }
+
+ /* IPv6 address to send from */
+ if (!strcmp(name, "local-ip-6")) {
+ param->local_address = value;
}
/* Protocol for the probe */
}
/* The local port to send UDP probes from */
- if (!strcmp(name, "localport")) {
+ if (!strcmp(name, "local-port")) {
param->local_port = strtol(value, &endstr, 10);
if (*endstr != 0) {
return false;
}
/* The packet's bytes will be filled with this value */
- if (!strcmp(name, "bitpattern")) {
+ if (!strcmp(name, "bit-pattern")) {
param->bit_pattern = strtol(value, &endstr, 10);
if (*endstr != 0) {
return false;
return 0;
}
+ if (bind(send_socket,
+ (struct sockaddr *)src_sockaddr, sizeof(struct sockaddr_in6))) {
+ return -1;
+ }
+
/* The traffic class in IPv6 is analagous to ToS in IPv4 */
if (setsockopt(
send_socket, IPPROTO_IPV6,
char *packet_buffer,
int packet_buffer_size,
const struct sockaddr_storage *dest_sockaddr,
+ const struct sockaddr_storage *src_sockaddr,
const struct probe_param_t *param)
{
int packet_size;
- struct sockaddr_storage src_sockaddr;
packet_size = compute_packet_size(net_state, param);
if (packet_size < 0) {
return -1;
}
- if (find_source_addr(&src_sockaddr, dest_sockaddr)) {
- return -1;
- }
-
memset(packet_buffer, param->bit_pattern, packet_size);
if (param->ip_version == 6) {
if (construct_ip6_packet(
net_state, packet_socket, sequence,
packet_buffer, packet_size,
- &src_sockaddr, dest_sockaddr, param)) {
+ src_sockaddr, dest_sockaddr, param)) {
return -1;
}
} else if (param->ip_version == 4) {
if (construct_ip4_packet(
net_state, packet_socket, sequence,
packet_buffer, packet_size,
- &src_sockaddr, dest_sockaddr, param)) {
+ src_sockaddr, dest_sockaddr, param)) {
return -1;
}
} else {
char *packet_buffer,
int packet_buffer_size,
const struct sockaddr_storage *dest_sockaddr,
+ const struct sockaddr_storage *src_sockaddr,
const struct probe_param_t *param);
#endif
#define IP_TEXT_LENGTH 64
/* Convert the destination address from text to sockaddr */
-int decode_dest_addr(
- const struct probe_param_t *param,
- struct sockaddr_storage *dest_sockaddr)
+int decode_address_string(
+ int ip_version,
+ const char *address_string,
+ struct sockaddr_storage *address)
{
- struct in_addr dest_addr4;
- struct in6_addr dest_addr6;
+ struct in_addr addr4;
+ struct in6_addr addr6;
struct sockaddr_in *sockaddr4;
struct sockaddr_in6 *sockaddr6;
- if (param->address == NULL) {
+ if (address == NULL) {
errno = EINVAL;
return -1;
}
- if (param->ip_version == 6) {
- sockaddr6 = (struct sockaddr_in6 *)dest_sockaddr;
+ if (ip_version == 6) {
+ sockaddr6 = (struct sockaddr_in6 *)address;
- if (inet_pton(AF_INET6, param->address, &dest_addr6) != 1) {
+ if (inet_pton(AF_INET6, address_string, &addr6) != 1) {
errno = EINVAL;
return -1;
}
sockaddr6->sin6_family = AF_INET6;
sockaddr6->sin6_port = 0;
sockaddr6->sin6_flowinfo = 0;
- sockaddr6->sin6_addr = dest_addr6;
+ sockaddr6->sin6_addr = addr6;
sockaddr6->sin6_scope_id = 0;
- } else if (param->ip_version == 4) {
- sockaddr4 = (struct sockaddr_in *)dest_sockaddr;
+ } else if (ip_version == 4) {
+ sockaddr4 = (struct sockaddr_in *)address;
- if (inet_pton(AF_INET, param->address, &dest_addr4) != 1) {
+ if (inet_pton(AF_INET, address_string, &addr4) != 1) {
errno = EINVAL;
return -1;
}
sockaddr4->sin_family = AF_INET;
sockaddr4->sin_port = 0;
- sockaddr4->sin_addr = dest_addr4;
+ sockaddr4->sin_addr = addr4;
} else {
errno = EINVAL;
return -1;
return 0;
}
+/*
+ Resolve the probe parameters into a remote and local address
+ for the probe.
+*/
+int resolve_probe_addresses(
+ const struct probe_param_t *param,
+ struct sockaddr_storage *dest_sockaddr,
+ struct sockaddr_storage *src_sockaddr)
+{
+ if (decode_address_string(
+ param->ip_version, param->remote_address, dest_sockaddr)) {
+ return -1;
+ }
+
+ if (param->local_address) {
+ if (decode_address_string(
+ param->ip_version, param->local_address, src_sockaddr)) {
+ return -1;
+ }
+ } else {
+ if (find_source_addr(src_sockaddr, dest_sockaddr)) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
/* Allocate a structure for tracking a new probe */
struct probe_t *alloc_probe(
struct net_state_t *net_state,
int command_token;
/* The IP address to probe */
- const char *address;
+ const char *remote_address;
+
+ /* The local address from which to send probes */
+ const char *local_address;
/* Protocol for the probe, using the IPPROTO_* defines */
int protocol;
int mpls_count,
const struct mpls_label_t *mpls);
-int decode_dest_addr(
+int decode_address_string(
+ int ip_version,
+ const char *address_string,
+ struct sockaddr_storage *address);
+
+int resolve_probe_addresses(
const struct probe_param_t *param,
- struct sockaddr_storage *dest_sockaddr);
+ struct sockaddr_storage *dest_sockaddr,
+ struct sockaddr_storage *src_sockaddr);
struct probe_t *alloc_probe(
struct net_state_t *net_state,
}
}
+/* Report a windows error code using a platform-independent error string */
+static
+void report_win_error(
+ int command_token,
+ int err)
+{
+ /* It could be that we got no reply because of timeout */
+ if (err == IP_REQ_TIMED_OUT) {
+ printf("%d no-reply\n", command_token);
+ } else if (err == IP_DEST_HOST_UNREACHABLE
+ || err == IP_DEST_NET_UNREACHABLE
+ || err == IP_DEST_UNREACHABLE
+ || err == IP_DEST_NO_ROUTE) {
+ printf("%d no-route\n", command_token);
+ } else if (err == ERROR_INVALID_NETNAME) {
+ printf("%d address-not-available\n", command_token);
+ } else if (err == ERROR_INVALID_PARAMETER) {
+ printf("%d invalid-argument\n", command_token);
+ } else {
+ printf("%d unexpected-error winerror %d\n", command_token, err);
+ }
+}
+
/*
The overlapped I/O style completion routine to be called by
Windows during an altertable wait when an ICMP probe has
if (reply_count == 0) {
err = GetLastError();
- /* It could be that we got no reply because of timeout */
- if (err == IP_REQ_TIMED_OUT) {
- printf("%d no-reply\n", probe->token);
-
- free_probe(probe);
- return;
- }
-
- fprintf(stderr, "IcmpParseReplies failure %d\n", err);
- exit(1);
+ report_win_error(probe->token, err);
+ free_probe(probe);
+ return;
}
DWORD timeout;
DWORD send_result;
int reply_size;
+ int err;
struct sockaddr_in *dest_sockaddr4;
struct sockaddr_in6 *src_sockaddr6;
struct sockaddr_in6 *dest_sockaddr6;
}
if (send_result == 0) {
+ err = GetLastError();
+
/*
ERROR_IO_PENDING is expected for asynchronous probes,
but any other error is unexpected.
*/
- if (GetLastError() != ERROR_IO_PENDING) {
- fprintf(stderr, "IcmpSendEcho2 failure %d\n", GetLastError());
- exit(1);
+ if (err != ERROR_IO_PENDING) {
+ report_win_error(probe->token, err);
+ free_probe(probe);
}
}
}
char payload[PACKET_BUFFER_SIZE];
int payload_size;
- if (decode_dest_addr(param, &dest_sockaddr)) {
+ if (resolve_probe_addresses(param, &dest_sockaddr, &src_sockaddr)) {
printf("%d invalid-argument\n", param->command_token);
return;
}
return;
}
- if (find_source_addr(&src_sockaddr, &dest_sockaddr)) {
- fprintf(stderr, "error finding source address\n");
- exit(1);
- }
-
probe->platform.ip_version = param->ip_version;
payload_size = fill_payload(param, payload, PACKET_BUFFER_SIZE);
char packet[PACKET_BUFFER_SIZE];
struct probe_param_t param;
struct sockaddr_storage dest_sockaddr;
+ struct sockaddr_storage src_sockaddr;
ssize_t bytes_sent;
int packet_size;
param.ip_version = 4;
param.protocol = IPPROTO_ICMP;
param.ttl = 255;
- param.address = "127.0.0.1";
+ param.remote_address = "127.0.0.1";
- if (decode_dest_addr(¶m, &dest_sockaddr)) {
+ if (resolve_probe_addresses(¶m, &dest_sockaddr, &src_sockaddr)) {
fprintf(stderr, "Error decoding localhost address\n");
exit(1);
}
packet_size = construct_packet(
net_state, NULL, MIN_PORT,
- packet, PACKET_BUFFER_SIZE, &dest_sockaddr, ¶m);
+ packet, PACKET_BUFFER_SIZE,
+ &dest_sockaddr, &src_sockaddr, ¶m);
if (packet_size < 0) {
perror("Unable to send to localhost");
exit(1);
packet_size = construct_packet(
net_state, NULL, MIN_PORT,
- packet, PACKET_BUFFER_SIZE, &dest_sockaddr, ¶m);
+ packet, PACKET_BUFFER_SIZE,
+ &dest_sockaddr, &src_sockaddr, ¶m);
if (packet_size < 0) {
perror("Unable to send to localhost");
exit(1);
printf("%d network-down\n", command_token);
} else if (errno == ENETUNREACH) {
printf("%d no-route\n", command_token);
+ } else if (errno == EHOSTUNREACH) {
+ printf("%d no-route\n", command_token);
} else if (errno == EPERM) {
printf("%d permission-denied\n", command_token);
} else if (errno == EADDRINUSE) {
printf("%d address-in-use\n", command_token);
+ } else if (errno == EADDRNOTAVAIL) {
+ printf("%d address-not-available\n", command_token);
} else {
printf("%d unexpected-error errno %d\n", command_token, errno);
}
char packet[PACKET_BUFFER_SIZE];
struct probe_t *probe;
int packet_size;
+ struct sockaddr_storage src_sockaddr;
probe = alloc_probe(net_state, param->command_token);
if (probe == NULL) {
return;
}
- if (decode_dest_addr(param, &probe->remote_addr)) {
+ if (resolve_probe_addresses(param, &probe->remote_addr, &src_sockaddr)) {
printf("%d invalid-argument\n", param->command_token);
free_probe(probe);
return;
packet_size = construct_packet(
net_state, &probe->platform.socket, probe->sequence,
- packet, PACKET_BUFFER_SIZE, &probe->remote_addr, param);
+ packet, PACKET_BUFFER_SIZE,
+ &probe->remote_addr, &src_sockaddr, param);
if (packet_size < 0) {
/*
'Test probes are filled with the requested bit pattern'
with mtrpacket.PacketListen('-4') as listen:
- cmd = '20 send-probe ip-4 127.0.0.1 bitpattern 44'
+ cmd = '20 send-probe ip-4 127.0.0.1 bit-pattern 44'
self.write_command(cmd)
'Test a variety of packet parameters'
with mtrpacket.PacketListen('-6') as listen:
- param = 'size 256 bitpattern 51 tos 77'
+ param = 'size 256 bit-pattern 51 tos 77'
cmd = '20 send-probe ip-6 ::1 ' + param
self.write_command(cmd)
reply = self.parse_reply()
self.assertEqual('reply', reply.command_name)
- cmd = '82 send-probe protocol udp localport 1991 ' + address
+ cmd = '82 send-probe protocol udp local-port 1991 ' + address
self.write_command(cmd)
reply = self.parse_reply()
self.assertEqual('reply', reply.command_name)