OpenWrt Forum Archive

Topic: Busybox PING patch for selecting interface

The content of this topic has been archived on 19 Apr 2018. There are no obvious gaps in this topic, but there may still be some posts missing at the end.

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
where eth1 is the interface you want to ping over and 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
+++ 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 ... */

        /* 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))
+       if (option_mask32 & 16) {
+               strncpy(device,opt_n,IFNAMSIZ);
+                               }
        myid = (int16_t) getpid();
        return EXIT_SUCCESS;

As the full blown ping uses -I to select a network interface, I would recommend to use the same option.
The option -n is usually used to select numeric output vs. resolve ip adresses to hostnames...

I would like to, except that -I is already used for another option. However, I am not tied to -n, if you can think if something more appropriate, please tell me.

Can I get this put into kamikaze trunk?

file a ticket on

The discussion might have continued from here.