Skip to content

Commit 33c99a1

Browse files
committed
Add --interface command line option
Passing --interface will force the packets through the specified interface instead of the default one. Signed-off-by: Andrea Barberio <[email protected]>
1 parent 2079431 commit 33c99a1

File tree

7 files changed

+59
-26
lines changed

7 files changed

+59
-26
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
*.dylib
55
build
66
go/dublintraceroute/cmd/dublin-traceroute/dublin-traceroute
7+
go/dublintraceroute/cmd/routest/routest
8+
.travis/trace.json
9+
integ/trace.json

include/dublintraceroute/dublin_traceroute.h

+13-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class DublinTraceroute {
5151
const bool broken_nat_,
5252
use_srcport_for_path_generation_,
5353
no_dns_;
54+
std::string interface_;
5455
std::mutex mutex_tracerouting,
5556
mutex_sniffed_packets;
5657
IPv4Address my_address;
@@ -67,6 +68,7 @@ class DublinTraceroute {
6768
static const bool default_broken_nat = false;
6869
static const bool default_use_srcport_for_path_generation = false;
6970
static const bool default_no_dns = false;
71+
static const std::string default_interface;
7072
DublinTraceroute(
7173
const std::string &dst,
7274
const uint16_t srcport = default_srcport,
@@ -77,7 +79,8 @@ class DublinTraceroute {
7779
const uint16_t delay = default_delay,
7880
const bool broken_nat = default_broken_nat,
7981
const bool use_srcport_for_path_generation = default_use_srcport_for_path_generation,
80-
const bool no_dns = default_no_dns
82+
const bool no_dns = default_no_dns,
83+
const std::string interface = default_interface
8184
):
8285
srcport_(srcport),
8386
dstport_(dstport),
@@ -88,7 +91,8 @@ class DublinTraceroute {
8891
delay_(delay),
8992
broken_nat_(broken_nat),
9093
use_srcport_for_path_generation_(use_srcport_for_path_generation),
91-
no_dns_(no_dns)
94+
no_dns_(no_dns),
95+
interface_(interface)
9296
{ validate_arguments(); }
9397
DublinTraceroute(
9498
const char *dst,
@@ -100,7 +104,8 @@ class DublinTraceroute {
100104
const uint16_t delay = default_delay,
101105
const bool broken_nat = default_broken_nat,
102106
const bool use_srcport_for_path_generation = default_use_srcport_for_path_generation,
103-
const bool no_dns = default_no_dns
107+
const bool no_dns = default_no_dns,
108+
const std::string interface = default_interface
104109
):
105110
srcport_(srcport),
106111
dstport_(dstport),
@@ -111,7 +116,8 @@ class DublinTraceroute {
111116
delay_(delay),
112117
broken_nat_(broken_nat),
113118
use_srcport_for_path_generation_(use_srcport_for_path_generation),
114-
no_dns_(no_dns)
119+
no_dns_(no_dns),
120+
interface_(interface)
115121
{ validate_arguments(); }
116122
~DublinTraceroute() { std::lock_guard<std::mutex> lock(mutex_tracerouting); };
117123
DublinTraceroute(const DublinTraceroute& source):
@@ -124,7 +130,8 @@ class DublinTraceroute {
124130
delay_(source.delay_),
125131
broken_nat_(source.broken_nat_),
126132
use_srcport_for_path_generation_(source.use_srcport_for_path_generation_),
127-
no_dns_(source.no_dns_)
133+
no_dns_(source.no_dns_),
134+
interface_(source.interface_)
128135
{ validate_arguments(); }
129136

130137
inline const uint16_t srcport() const { return srcport_; }
@@ -135,6 +142,7 @@ class DublinTraceroute {
135142
inline const uint16_t delay() const { return delay_; }
136143
inline const bool broken_nat() const { return broken_nat_; }
137144
inline const bool no_dns() const { return no_dns_; }
145+
inline const std::string interface() const { return interface_; }
138146
inline const bool use_srcport_for_path_generation() const { return use_srcport_for_path_generation_; }
139147
inline const std::string &dst() const { return dst_; }
140148
inline const IPv4Address &target() const { return target_; }

include/dublintraceroute/udpv4probe.h

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class UDPv4Probe {
2525
uint16_t local_port_;
2626
uint16_t remote_port_;
2727
uint8_t ttl_;
28+
std::string interface_;
2829
IP *packet = nullptr;
2930

3031
public:
@@ -33,17 +34,20 @@ class UDPv4Probe {
3334
const uint16_t local_port() const { return local_port_; };
3435
const uint16_t remote_port() const { return remote_port_; };
3536
const uint8_t ttl() const { return ttl_; };
37+
const std::string interface() const { return interface_; };
3638

3739
UDPv4Probe(
3840
IPv4Address remote_addr,
3941
uint16_t remote_port,
4042
uint16_t local_port,
4143
uint8_t ttl,
44+
std::string interface = "",
4245
IPv4Address local_addr = 0):
4346
remote_addr_(remote_addr),
4447
remote_port_(remote_port),
4548
local_port_(local_port),
4649
ttl_(ttl),
50+
interface_(interface),
4751
local_addr_(local_addr) { };
4852
~UDPv4Probe();
4953
IP* forge();

src/dublin_traceroute.cc

+4-2
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ extern int errno;
4141

4242
#define SNIFFER_TIMEOUT_MS 2000
4343

44+
// this is not necessary in C++17 and can be assigned in the header file.
45+
const std::string DublinTraceroute::default_interface = "";
4446

4547
Tins::Timestamp extract_timestamp_from_msg(struct msghdr &msg) {
4648
int level, type;
@@ -218,10 +220,10 @@ std::shared_ptr<TracerouteResults> DublinTraceroute::traceroute() {
218220

219221
UDPv4Probe *probe = NULL;
220222
if(use_srcport_for_path_generation()){
221-
probe = new UDPv4Probe(target(), dstport(), iterated_port, ttl);
223+
probe = new UDPv4Probe(target(), dstport(), iterated_port, ttl, interface());
222224
}
223225
else{
224-
probe = new UDPv4Probe(target(), iterated_port, srcport(), ttl);
226+
probe = new UDPv4Probe(target(), iterated_port, srcport(), ttl, interface());
225227
//UDPv4Probe probe(target(), dport, srcport(), ttl);
226228
}
227229
IP *packet;

src/main.cc

+28-15
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ const struct option longopts[] = {
3232
{"broken-nat", no_argument, NULL, 'b'},
3333
{"use-srcport", no_argument, NULL, 'i'},
3434
{"no-dns", no_argument, NULL, 'N'},
35+
{"interface", required_argument, NULL, 'I'},
3536
{"output-file", required_argument, NULL, 'o'},
3637
{NULL, 0, NULL, 0},
3738
};
@@ -51,23 +52,25 @@ R"(Written by Andrea Barberio - https://insomniac.slackware.it
5152
[--broken-nat]
5253
[--use-srcport]
5354
[--no-dns]
55+
[--interface=ifname]
5456
[--output-file=file_name]
5557
[--help]
5658
[--version]
5759
5860
Options:
59-
-h --help this help
60-
-v --version print the version of Dublin Traceroute
61-
-s SRC_PORT --sport=SRC_PORT the source port to send packets from (default: )" << DublinTraceroute::default_srcport << R"()
62-
-d DST_PORT --dport=DST_PORT the base destination port to send packets to (default: )" << DublinTraceroute::default_dstport << R"()
63-
-n NPATHS --npaths=NPATHS the number of paths to probe (default: )" << static_cast<int>(DublinTraceroute::default_npaths) << R"()
64-
-t MIN_TTL --min-ttl=MIN_TTL the minimum TTL to probe (default: )" << static_cast<int>(DublinTraceroute::default_min_ttl) << R"()
65-
-T MAX_TTL --max-ttl=MAX_TTL the maximum TTL to probe. Must be greater or equal than the minimum TTL (default: )" << static_cast<int>(DublinTraceroute::default_max_ttl) << R"()
66-
-D DELAY --delay=DELAY the inter-packet delay in milliseconds (default: )" << DublinTraceroute::default_delay << R"()
67-
-b --broken-nat the network has a broken NAT configuration (e.g. no payload fixup). Try this if you see fewer hops than expected
68-
-i --use-srcport generate paths using source port instead of destination port
69-
-N --no-dns do not attempt to do reverse DNS lookup of the hops
70-
-o --output-file the output file name (default: )" << DEFAULT_OUTPUT_FILE << R"()
61+
-h, --help this help
62+
-v, --version print the version of Dublin Traceroute
63+
-s, --sport=SRC_PORT the source port to send packets from (default: )" << DublinTraceroute::default_srcport << R"()
64+
-d, --dport=DST_PORT the base destination port to send packets to (default: )" << DublinTraceroute::default_dstport << R"()
65+
-n, --npaths=NPATHS the number of paths to probe (default: )" << static_cast<int>(DublinTraceroute::default_npaths) << R"()
66+
-t, --min-ttl=MIN_TTL the minimum TTL to probe (default: )" << static_cast<int>(DublinTraceroute::default_min_ttl) << R"()
67+
-T, --max-ttl=MAX_TTL the maximum TTL to probe. Must be greater or equal than the minimum TTL (default: )" << static_cast<int>(DublinTraceroute::default_max_ttl) << R"()
68+
-D, --delay=DELAY the inter-packet delay in milliseconds (default: )" << DublinTraceroute::default_delay << R"()
69+
-b, --broken-nat the network has a broken NAT configuration (e.g. no payload fixup). Try this if you see fewer hops than expected
70+
-i, --use-srcport generate paths using source port instead of destination port
71+
-N, --no-dns do not attempt to do reverse DNS lookup of the hops
72+
-I, --interface=INTERFACE force packets through the specified interface. If not specified, the default interface for the target will be used
73+
-o, --output-file=OUTFILE the output file name (default: )" << DEFAULT_OUTPUT_FILE << R"()
7174
7275
7376
See documentation at https://dublin-traceroute.net
@@ -89,6 +92,7 @@ main(int argc, char **argv) {
8992
bool broken_nat = DublinTraceroute::default_broken_nat;
9093
bool use_srcport_for_path_generation = DublinTraceroute::default_use_srcport_for_path_generation;
9194
bool no_dns = DublinTraceroute::default_no_dns;
95+
std::string interface = DublinTraceroute::default_interface;
9296
std::string output_file = DEFAULT_OUTPUT_FILE;
9397

9498
if (geteuid() == 0) {
@@ -143,6 +147,9 @@ main(int argc, char **argv) {
143147
case 'N':
144148
no_dns = true;
145149
break;
150+
case 'I':
151+
interface = optarg;
152+
break;
146153
case 'o':
147154
output_file.assign(optarg);
148155
break;
@@ -215,18 +222,24 @@ main(int argc, char **argv) {
215222
delay,
216223
broken_nat,
217224
use_srcport_for_path_generation,
218-
no_dns
225+
no_dns,
226+
interface
219227
);
220228

221229
std::cout << "Traceroute from 0.0.0.0:" << Dublin.srcport();
222-
if(use_srcport_for_path_generation == 1){
230+
if (use_srcport_for_path_generation == 1){
223231
std::cout << "~" << (Dublin.srcport() + npaths - 1);
224232
}
225233

226234
std::cout << " to " << Dublin.dst() << ":" << Dublin.dstport();
227-
if(use_srcport_for_path_generation == 0){
235+
if (use_srcport_for_path_generation == 0){
228236
std::cout << "~" << (Dublin.dstport() + npaths - 1);
229237
}
238+
if (interface != "") {
239+
std::cout << " through interface " << interface;
240+
} else {
241+
std::cout << " through default interface";
242+
}
230243

231244
std::cout << " (probing " << npaths << " path" << (npaths == 1 ? "" : "s")
232245
<< ", min TTL is " << min_ttl

src/udpv4probe.cc

+5-2
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,15 @@ IP* UDPv4Probe::forge() {
5555
}
5656

5757
IP &UDPv4Probe::send() {
58-
NetworkInterface iface = NetworkInterface::default_interface();
58+
std::string ifname = NetworkInterface::default_interface().name();
59+
if (interface_ != "") {
60+
ifname = interface_;
61+
}
5962
PacketSender sender;
6063
if (packet == nullptr) {
6164
packet = forge();
6265
}
63-
sender.send(*packet, iface.name());
66+
sender.send(*packet, ifname);
6467
return *packet;
6568
}
6669

tests/src/udpv4.cxx

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class UDPv4Test: public ::testing::Test {
1212
};
1313

1414
TEST_F(UDPv4Test, TestUDPv4Constructor) {
15-
UDPv4Probe p = UDPv4Probe(IPv4Address("8.8.8.8"), 33434, 12345, 64, IPv4Address("127.0.0.2"));
15+
UDPv4Probe p = UDPv4Probe(IPv4Address("8.8.8.8"), 33434, 12345, 64, "", IPv4Address("127.0.0.2"));
1616
ASSERT_EQ(p.local_port(), 12345);
1717
ASSERT_EQ(p.remote_port(), 33434);
1818
ASSERT_EQ(p.ttl(), 64);
@@ -30,7 +30,7 @@ TEST_F(UDPv4Test, TestUDPv4ConstructorDefaultLocalAddr) {
3030
}
3131

3232
TEST_F(UDPv4Test, TestUDPv4PacketForging) {
33-
UDPv4Probe p = UDPv4Probe(IPv4Address("127.0.0.3"), 33434, 12345, 64, IPv4Address("127.0.0.2"));
33+
UDPv4Probe p = UDPv4Probe(IPv4Address("127.0.0.3"), 33434, 12345, 64, "", IPv4Address("127.0.0.2"));
3434
IP* ip = p.forge();
3535
ASSERT_EQ(ip->tos(), 0);
3636
ASSERT_EQ(ip->id(), 60794);

0 commit comments

Comments
 (0)