From 8430389f2ba7b810cc7ccb1dd1ce526a143f3bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Taveira=20Ara=C3=BAjo?= Date: Wed, 18 Jun 2014 19:55:52 +0100 Subject: [PATCH] Add support for setting SO_MARK through --mark option. This emulates the -m option for ping provided in iputils. When coupled with iptables, this option provides a means of using source routing to force probes through a consistent nexthop on multihomed systems. --- mtr.c | 18 ++++++++++++++++++ net.c | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/mtr.c b/mtr.c index 416b744b..72252863 100644 --- a/mtr.c +++ b/mtr.c @@ -76,6 +76,9 @@ int enablempls = 0; int cpacketsize = 64; /* default packet size */ int bitpattern = 0; int tos = 0; +#ifdef SO_MARK +int mark = -1; +#endif int reportwide = 0; int af = DEFAULT_AF; int mtrtype = IPPROTO_ICMP; /* Use ICMP as default packet type */ @@ -293,6 +296,9 @@ void parse_arg (int argc, char **argv) #ifdef IPINFO { "ipinfo", 1, 0, 'y' }, /* IP info lookup */ { "aslookup", 0, 0, 'z' }, /* Do AS lookup (--ipinfo 0) */ +#endif +#ifdef SO_MARK + { "mark", 1, 0, 'M' }, /* use SO_MARK */ #endif { 0, 0, 0, 0 } }; @@ -470,6 +476,15 @@ void parse_arg (int argc, char **argv) case 'z': fprintf( stderr, "IPINFO not enabled.\n" ); break; +#endif +#ifdef SO_MARK + case 'M': + mark = atoi (optarg); + if (mark < 0) { + fprintf( stderr, "SO_MARK must be positive.\n" ); + exit(EXIT_FAILURE); + } + break; #endif } } @@ -579,6 +594,9 @@ int main(int argc, char **argv) #ifdef IPINFO "\t\t[--ipinfo=item_no|-y item_no]\n" "\t\t[--aslookup|-z]\n" +#endif +#ifdef SO_MARK + "\t\t[--mark=NUM]\n" #endif "\t\t[--psize=bytes/-s bytes] [--order fields]\n" /* ok */ "\t\t[--report-wide|-w] [--inet] [--inet6] [--max-ttl=NUM] [--first-ttl=NUM]\n" diff --git a/net.c b/net.c index 0721ad71..7d51fd02 100644 --- a/net.c +++ b/net.c @@ -210,6 +210,9 @@ extern int af; /* address family of remote target */ extern int mtrtype; /* type of query packet used */ extern int remoteport; /* target port for TCP tracing */ extern int timeout; /* timeout for TCP connections */ +#ifdef SO_MARK +extern int mark; /* SO_MARK to set for ping packet*/ +#endif /* return the number of microseconds to wait before sending the next ping */ @@ -381,6 +384,13 @@ void net_send_tcp(int index) #endif } +#ifdef SO_MARK + if (mark >= 0 && setsockopt( s, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) { + perror( "setsockopt SO_MARK" ); + exit( EXIT_FAILURE ); + } +#endif + switch (local.ss_family) { case AF_INET: port = ntohs(local4->sin_port); @@ -481,6 +491,13 @@ void net_send_query(int index) #endif } +#ifdef SO_MARK + if (mark >= 0 && setsockopt( sendsock, SOL_SOCKET, SO_MARK, &mark, sizeof mark ) ) { + perror( "setsockopt SO_MARK" ); + exit( EXIT_FAILURE ); + } +#endif + switch ( mtrtype ) { case IPPROTO_ICMP: icmp = (struct ICMPHeader *)(packet + iphsize);