u_short, ulong exterminated
[oweals/busybox.git] / networking / ping.c
index 4269eaa6fbd4164f2d6a47af2af0ac95e5acb03a..658c015180dde346f32e4fa3f515db695f92ecb2 100644 (file)
@@ -41,17 +41,10 @@ enum {
        PINGINTERVAL = 1                /* second */
 };
 
-#define O_QUIET         (1 << 0)
-
-#define        A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in array */
-#define        B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte */
-#define        SET(bit)        (A(bit) |= B(bit))
-#define        CLR(bit)        (A(bit) &= (~B(bit)))
-#define        TST(bit)        (A(bit) & B(bit))
-
 static void ping(const char *host);
 
 /* common routines */
+
 static int in_cksum(unsigned short *buf, int sz)
 {
        int nleft = sz;
@@ -72,11 +65,13 @@ static int in_cksum(unsigned short *buf, int sz)
        sum = (sum >> 16) + (sum & 0xFFFF);
        sum += (sum >> 16);
        ans = ~sum;
-       return (ans);
+       return ans;
 }
 
-/* simple version */
 #ifndef CONFIG_FEATURE_FANCY_PING
+
+/* simple version */
+
 static char *hostname;
 
 static void noresp(int ign)
@@ -153,14 +148,21 @@ int ping_main(int argc, char **argv)
 }
 
 #else /* ! CONFIG_FEATURE_FANCY_PING */
+
 /* full(er) version */
+
+#define OPT_STRING "qc:s:I:"
+enum {
+       OPT_QUIET = 1 << 0,
+};
+
 static struct sockaddr_in pingaddr;
 static struct sockaddr_in sourceaddr;
 static int pingsock = -1;
-static int datalen; /* intentionally uninitialized to work around gcc bug */
+static unsigned datalen; /* intentionally uninitialized to work around gcc bug */
 
-static long ntransmitted, nreceived, nrepeats, pingcount;
-static int myid, options;
+static unsigned long ntransmitted, nreceived, nrepeats, pingcount;
+static int myid;
 static unsigned long tmin = ULONG_MAX, tmax, tsum;
 static char rcvd_tbl[MAX_DUP_CHK / 8];
 
@@ -170,6 +172,12 @@ static void sendping(int);
 static void pingstats(int);
 static void unpack(char *, int, struct sockaddr_in *);
 
+#define        A(bit)          rcvd_tbl[(bit)>>3]      /* identify byte in array */
+#define        B(bit)          (1 << ((bit) & 0x07))   /* identify bit in byte */
+#define        SET(bit)        (A(bit) |= B(bit))
+#define        CLR(bit)        (A(bit) &= (~B(bit)))
+#define        TST(bit)        (A(bit) & B(bit))
+
 /**************************************************************************/
 
 static void pingstats(int junk)
@@ -179,12 +187,12 @@ static void pingstats(int junk)
        signal(SIGINT, SIG_IGN);
 
        printf("\n--- %s ping statistics ---\n", hostent->h_name);
-       printf("%ld packets transmitted, ", ntransmitted);
-       printf("%ld packets received, ", nreceived);
+       printf("%lu packets transmitted, ", ntransmitted);
+       printf("%lu packets received, ", nreceived);
        if (nrepeats)
-               printf("%ld duplicates, ", nrepeats);
+               printf("%lu duplicates, ", nrepeats);
        if (ntransmitted)
-               printf("%ld%% packet loss\n",
+               printf("%lu%% packet loss\n",
                           (ntransmitted - nreceived) * 100 / ntransmitted);
        if (nreceived)
                printf("round-trip min/avg/max = %lu.%lu/%lu.%lu/%lu.%lu ms\n",
@@ -304,7 +312,7 @@ static void unpack(char *buf, int sz, struct sockaddr_in *from)
                        dupflag = 0;
                }
 
-               if (options & O_QUIET)
+               if (option_mask32 & OPT_QUIET)
                        return;
 
                printf("%d bytes from %s: icmp_seq=%u", sz,
@@ -314,10 +322,10 @@ static void unpack(char *buf, int sz, struct sockaddr_in *from)
                printf(" time=%lu.%lu ms", triptime / 10, triptime % 10);
                if (dupflag)
                        printf(" (DUP!)");
-               printf("\n");
+               puts("");
        } else
                if (icmppkt->icmp_type != ICMP_ECHO)
-                       bb_error_msg("Warning: Got ICMP %d (%s)",
+                       bb_error_msg("warning: got ICMP %d (%s)",
                                        icmppkt->icmp_type, icmp_type_name(icmppkt->icmp_type));
        fflush(stdout);
 }
@@ -330,8 +338,7 @@ static void ping(const char *host)
        pingsock = create_icmp_socket();
 
        if (sourceaddr.sin_addr.s_addr) {
-               if (bind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr)) == -1)
-                       bb_error_msg_and_die("could not bind to address");
+               xbind(pingsock, (struct sockaddr*)&sourceaddr, sizeof(sourceaddr));
        }
 
        memset(&pingaddr, 0, sizeof(struct sockaddr_in));
@@ -344,9 +351,7 @@ static void ping(const char *host)
        memcpy(&pingaddr.sin_addr, hostent->h_addr, sizeof(pingaddr.sin_addr));
 
        /* enable broadcast pings */
-       sockopt = 1;
-       setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
-                          sizeof(sockopt));
+       setsockopt_broadcast(pingsock);
 
        /* set recv buf for broadcast pings */
        sockopt = 48 * 1024;
@@ -410,55 +415,26 @@ static int parse_nipquad(const char *str, struct sockaddr_in* addr)
 
 int ping_main(int argc, char **argv)
 {
-       char *thisarg;
+       char *opt_c, *opt_s, *opt_I;
 
        datalen = DEFDATALEN; /* initialized here rather than in global scope to work around gcc bug */
 
-       argc--;
-       argv++;
-       /* Parse any options */
-       while (argc >= 1 && **argv == '-') {
-               thisarg = *argv;
-               thisarg++;
-               switch (*thisarg) {
-               case 'q':
-                       options |= O_QUIET;
-                       break;
-               case 'c':
-                       if (--argc <= 0)
-                               bb_show_usage();
-                       argv++;
-                       pingcount = atoi(*argv);
-                       break;
-               case 's':
-                       if (--argc <= 0)
-                               bb_show_usage();
-                       argv++;
-                       datalen = atoi(*argv);
-                       break;
-               case 'I':
-                       if (--argc <= 0)
-                               bb_show_usage();
-                       argv++;
-/* ping6 accepts iface too:
-                       if_index = if_nametoindex(*argv);
-                       if (!if_index) ...
-   make it true for ping too. TODO.
-*/
-                       if (parse_nipquad(*argv, &sourceaddr))
-                               bb_show_usage();
-                       break;
-               default:
+       /* exactly one argument needed */
+       opt_complementary = "=1";
+       getopt32(argc, argv, OPT_STRING, &opt_c, &opt_s, &opt_I);
+       if (option_mask32 & 2) pingcount = xatoul(opt_c); // -c
+       if (option_mask32 & 4) datalen = xatou16(opt_s); // -s
+       if (option_mask32 & 8) { // -I
+/* TODO: ping6 accepts iface too:
+               if_index = if_nametoindex(*argv);
+               if (!if_index) ...
+make it true for ping. */
+               if (parse_nipquad(opt_I, &sourceaddr))
                        bb_show_usage();
-               }
-               argc--;
-               argv++;
        }
-       if (argc < 1)
-               bb_show_usage();
 
        myid = (int16_t) getpid();
-       ping(*argv);
+       ping(argv[optind]);
        return EXIT_SUCCESS;
 }
 #endif /* ! CONFIG_FEATURE_FANCY_PING */