It's useful to be able to select which interface a ping will go out over. This is most useful for when you have multiple upstreams, on of which is preferred. Say for instance, you have your own cable modem but have arranged with your neighbor to use his DSL modem in case you have a problem with your cable modem. It's easy enough to know when your modem is broken, and to change the default route to be your interface to your neighbor's cable modem. The problem is knowing when to switch back, without temporarily changing the default route back to your cable modem and trying it. With this patch, you can ping out to some central location on the Internet every so often over your cable modem, while the rest of your traffic flows over your neighbor's dsl modem. When your ping finally gets responses, you can switch the default route back over to your cable modem.
the usage will be
ping -n eth1 4.2.2.2
where eth1 is the interface you want to ping over and 4.2.2.2 is the destination.
Below is the patch. I'd appreciate your testing it, and post and problems or success here on this thread. When it's shown to be working well, I hope that OpenWRT will include it and eventually BusyBox will make it an option as well.
--- busybox-1.4.2.orig/networking/ping.c 2007-03-18 12:59:24.000000000 -0400
+++ busybox-1.4.2.new/networking/ping.c 2007-10-07 19:45:42.000000000 -0400
@@ -14,6 +14,7 @@
#include <netinet/ip_icmp.h>
#include "busybox.h"
+#include <net/if.h>
enum {
DEFDATALEN = 56,
@@ -134,11 +135,11 @@
/* full(er) version */
-#define OPT_STRING "qc:s:I:"
+#define OPT_STRING "qc:s:I:n:"
enum {
OPT_QUIET = 1 << 0,
};
-
+char device[IFNAMSIZ];
static struct sockaddr_in pingaddr;
static struct sockaddr_in sourceaddr;
static int pingsock = -1;
@@ -207,7 +208,9 @@
gettimeofday((struct timeval *) &pkt->icmp_dun, NULL);
pkt->icmp_cksum = in_cksum((unsigned short *) pkt, sizeof(packet));
-
+ if ( option_mask32 & 16 ) {
+ setsockopt(pingsock, SOL_SOCKET, SO_BINDTODEVICE, device, IFNAMSIZ+1);
+ }
i = sendto(pingsock, packet, sizeof(packet), 0,
(struct sockaddr *) &pingaddr, sizeof(struct sockaddr_in));
@@ -354,7 +357,7 @@
signal(SIGINT, pingstats);
- /* start the ping's going ... */
+ /* start the pings going ... */
sendping(0);
/* listen for replies */
@@ -400,13 +403,13 @@
int ping_main(int argc, char **argv)
{
- char *opt_c, *opt_s, *opt_I;
+ char *opt_c, *opt_s, *opt_I, *opt_n;
datalen = DEFDATALEN; /* initialized here rather than in global scope to work around gcc bug */
/* exactly one argument needed */
opt_complementary = "=1";
- getopt32(argc, argv, OPT_STRING, &opt_c, &opt_s, &opt_I);
+ getopt32(argc, argv, OPT_STRING, &opt_c, &opt_s, &opt_I, &opt_n);
if (option_mask32 & 2) pingcount = xatoul(opt_c); // -c
if (option_mask32 & 4) datalen = xatou16(opt_s); // -s
if (option_mask32 & 8) { // -I
@@ -417,7 +420,9 @@
if (parse_nipquad(opt_I, &sourceaddr))
bb_show_usage();
}
-
+ if (option_mask32 & 16) {
+ strncpy(device,opt_n,IFNAMSIZ);
+ }
myid = (int16_t) getpid();
ping(argv[optind]);
return EXIT_SUCCESS;