summaryrefslogtreecommitdiff
path: root/sbin/ping/ping.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbin/ping/ping.c')
-rw-r--r--sbin/ping/ping.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/sbin/ping/ping.c b/sbin/ping/ping.c
index 3609ae2fe621..13f3344cbcbb 100644
--- a/sbin/ping/ping.c
+++ b/sbin/ping/ping.c
@@ -105,6 +105,12 @@ int options;
#define F_SO_DONTROUTE 0x080
#define F_VERBOSE 0x100
+/* multicast options */
+int moptions;
+#define MULTICAST_NOLOOP 0x001
+#define MULTICAST_TTL 0x002
+#define MULTICAST_IF 0x004
+
/*
* MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
* number of received sequence numbers we can keep track of. Change 128
@@ -149,17 +155,19 @@ main(argc, argv)
struct hostent *hp;
struct sockaddr_in *to;
struct protoent *proto;
- register int i;
+ struct in_addr ifaddr;
+ int i;
int ch, fdmask, hold, packlen, preload;
u_char *datap, *packet;
char *target, hnamebuf[MAXHOSTNAMELEN], *malloc();
+ u_char ttl, loop;
#ifdef IP_OPTIONS
char rspace[3 + 4 * NROUTES + 1]; /* record route space */
#endif
preload = 0;
datap = &outpack[8 + sizeof(struct timeval)];
- while ((ch = getopt(argc, argv, "Rc:dfh:i:l:np:qrs:v")) != EOF)
+ while ((ch = getopt(argc, argv, "I:LRc:dfh:i:l:np:qrs:t:v")) != EOF)
switch(ch) {
case 'c':
npackets = atoi(optarg);
@@ -230,12 +238,40 @@ main(argc, argv)
case 'v':
options |= F_VERBOSE;
break;
+ case 'L':
+ moptions |= MULTICAST_NOLOOP;
+ loop = 0;
+ break;
+ case 't':
+ moptions |= MULTICAST_TTL;
+ i = atoi(optarg);
+ if (i < 0 || i > 255) {
+ printf("ttl %u out of range\n", i);
+ exit(1);
+ }
+ ttl = i;
+ break;
+ case 'I':
+ moptions |= MULTICAST_IF;
+ {
+ int i1, i2, i3, i4;
+
+ if (sscanf(optarg, "%u.%u.%u.%u%c",
+ &i1, &i2, &i3, &i4, &i) != 4) {
+ printf("bad interface address '%s'\n",
+ optarg);
+ exit(1);
+ }
+ ifaddr.s_addr = (i1<<24)|(i2<<16)|(i3<<8)|i4;
+ ifaddr.s_addr = htonl(ifaddr.s_addr);
+ }
+ break;
default:
usage();
}
argc -= optind;
argv += optind;
-
+
if (argc != 1)
usage();
target = *argv;
@@ -322,6 +358,28 @@ main(argc, argv)
(void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
sizeof(hold));
+ if (moptions & MULTICAST_NOLOOP) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,
+ &loop, 1) == -1) {
+ perror ("can't disable multicast loopback");
+ exit(92);
+ }
+ }
+ if (moptions & MULTICAST_TTL) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL,
+ &ttl, 1) == -1) {
+ perror ("can't set multicast time-to-live");
+ exit(93);
+ }
+ }
+ if (moptions & MULTICAST_IF) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
+ &ifaddr, sizeof(ifaddr)) == -1) {
+ perror ("can't set multicast source interface");
+ exit(94);
+ }
+ }
+
if (to->sin_family == AF_INET)
(void)printf("PING %s (%s): %d data bytes\n", hostname,
inet_ntoa(*(struct in_addr *)&to->sin_addr.s_addr),
@@ -990,6 +1048,6 @@ fill(bp, patp)
usage()
{
(void)fprintf(stderr,
- "usage: ping [-Rdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] host\n");
+ "usage: ping [-LRdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] [-t ttl] [-I interface address] host\n");
exit(1);
}