pingのデフォルト送信先

ネットワークの導通を確認する場合には、まずはデフォルトゲートウェイpingを打ってみると思います。それならば、引数をつけずにpingを実行したら、デフォルトゲートウェイ宛てにpingを送信してくれてもよさそうなものです。ということで、NetBSD-2.0.2のping.c(1.75)に対するpatchを作ってみました。kmemまわりを使ってデフォルトゲートウェイを求める処理が面倒なので、popen(3)を使って手を抜いています(^^;;

diff -ruN ping.orig/ping.c ping/ping.c
--- ping.orig/ping.c	2005-10-09 21:53:05.000000000 +0900
+++ ping/ping.c	2005-10-23 06:06:56.000000000 +0900
@@ -241,6 +241,7 @@
 static void gethost(const char *, const char *,
 		    struct sockaddr_in *, char *, int);
 static void usage(void);
+static int get_default_gw_addr(char *, size_t);
 
 
 int
@@ -260,7 +261,8 @@
 	char *policy_out = NULL;
 #endif
 #endif
-  
+	char *addrp;
+	char addr[128];
 
 	setprogname(argv[0]);
 
@@ -426,15 +428,23 @@
 	}
 
 	if (hostind == 0) {
-		if (optind != argc-1)
-			usage();
-		else
+		if (optind != argc-1) {
+			if (get_default_gw_addr(addr, sizeof addr) != 0)
+		    		usage();
+			addrp = addr;
+		} else {
 			hostind = optind;
+			addrp = argv[hostind];
+		}
+	} else if (hostind >= argc - 1) {
+		if (get_default_gw_addr(addr, sizeof addr) != 0)
+			usage();
+		addrp = addr;
+	} else {
+		addrp = argv[hostind];
 	}
-	else if (hostind >= argc - 1)
-		usage();
 
-	gethost("", argv[hostind], &whereto, hostname, sizeof(hostname));
+	gethost("", addrp, &whereto, hostname, sizeof(hostname));
 	if (IN_MULTICAST(ntohl(whereto.sin_addr.s_addr)))
 		pingflags |= F_MCAST;
 	if (!(pingflags & F_SOURCE_ROUTE))
@@ -1850,3 +1860,27 @@
 	    getprogname());
 	exit(1);
 }
+
+static int
+get_default_gw_addr(char *addr, size_t len)
+{
+	char buf[128];
+	size_t n;
+
+	FILE *p = popen("/usr/bin/netstat -rn "
+		"| /usr/bin/grep default "
+		"| /usr/bin/awk '{print $2}'",
+		"r");
+	
+	if (fgets(buf, sizeof buf, p) == NULL)
+		return -1;
+	pclose(p);
+
+	if ((n = strlen(buf)) == 0)
+		return -2;
+	
+	buf[n - 1] = '\0';
+	strlcpy(addr, buf, len);
+	
+	return 0;
+}

BUGS: IPv4IPv6の混在とか全然考えていません。だめじゃん。