From 5a7c2a52a548352950a4cb668cd4b7c2362be194 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Jan 2015 17:16:32 -0600 Subject: [PATCH 1/7] renamed README to a .txt and created new folder with githubname with copies of files from src --- README.md | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 README.md diff --git a/README.md b/README.md deleted file mode 100644 index 74c48a0..0000000 --- a/README.md +++ /dev/null @@ -1,20 +0,0 @@ - -1. You should be reading this file from your own file system, not a web browser. -2. Navigate to the src/ directory. In here, you will see some source code. -3. Create a new folder named exactly your GitHub username. Then copy, not move, the source code files into the new folder. - -You’ve now made an atomic change in code. Before any commits, make sure you set your user.name and user.email to match up with your GitHub user name and email. - -4. Add your created files. -5. Commit your changes. Make sure your commit message is meaningful and describes what changes you made. -6. From those files in your newly created directory, make changes to both of them. What you change does not matter, but try to make it fairly significant. For example, delete half of the repository or write a poem in comments. I don't expect you to run it. -7. Commit your changes. -8. Push up your changes to master. Remember you've forked the project, changesets go to your own instance of the repository, not mine. -9. Navigate to the res/ directory. It will be empty. -10. Create a new folder named exactly your GitHub username and navigate to it. -11. Draw a picture in MS Paint (or whatever) and throw it into your folder. -12. Add the file. -13. Commit the file. -14. Push up the changes. -15. Create a Pull Request back from your repository, to mine; sstutsman/assignment-one. Remember, this is done on GitHub.com, not through Git Bash. For the request, the base fork will be sstutsman/assignment-one. For the head fork, it will be YourUserName/assignment-one -16. GitHub will then prompt you for a title. Make sure you add your full, real name (not your GitHub username) for my sake. From 54a1b2c47d74c8be0e1c14b9d09fa5238f09cb8e Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Jan 2015 17:23:20 -0600 Subject: [PATCH 2/7] deleted csv and time settings in pong.cpp/erased counters and protos in ping.c --- README.txt | 20 + moralesty1/.DS_Store | Bin 0 -> 6148 bytes moralesty1/ping.c | 1175 ++++++++++++++++++++++++++++++++++++++++++ moralesty1/pong.cpp | 968 ++++++++++++++++++++++++++++++++++ 4 files changed, 2163 insertions(+) create mode 100644 README.txt create mode 100644 moralesty1/.DS_Store create mode 100644 moralesty1/ping.c create mode 100644 moralesty1/pong.cpp diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..74c48a0 --- /dev/null +++ b/README.txt @@ -0,0 +1,20 @@ + +1. You should be reading this file from your own file system, not a web browser. +2. Navigate to the src/ directory. In here, you will see some source code. +3. Create a new folder named exactly your GitHub username. Then copy, not move, the source code files into the new folder. + +You’ve now made an atomic change in code. Before any commits, make sure you set your user.name and user.email to match up with your GitHub user name and email. + +4. Add your created files. +5. Commit your changes. Make sure your commit message is meaningful and describes what changes you made. +6. From those files in your newly created directory, make changes to both of them. What you change does not matter, but try to make it fairly significant. For example, delete half of the repository or write a poem in comments. I don't expect you to run it. +7. Commit your changes. +8. Push up your changes to master. Remember you've forked the project, changesets go to your own instance of the repository, not mine. +9. Navigate to the res/ directory. It will be empty. +10. Create a new folder named exactly your GitHub username and navigate to it. +11. Draw a picture in MS Paint (or whatever) and throw it into your folder. +12. Add the file. +13. Commit the file. +14. Push up the changes. +15. Create a Pull Request back from your repository, to mine; sstutsman/assignment-one. Remember, this is done on GitHub.com, not through Git Bash. For the request, the base fork will be sstutsman/assignment-one. For the head fork, it will be YourUserName/assignment-one +16. GitHub will then prompt you for a title. Make sure you add your full, real name (not your GitHub username) for my sake. diff --git a/moralesty1/.DS_Store b/moralesty1/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..190c3c6723b3c0f3994d6e6419a9d0115a250c8e GIT binary patch literal 6148 zcmeHKu}T9$5S>Ya1Z+}TZfPa>2TO>8wLc(w^w_! z7n|1er9R=;@a5@*$QS9YJ99DaNBfa~4<~<-d<=c$p8QV literal 0 HcmV?d00001 diff --git a/moralesty1/ping.c b/moralesty1/ping.c new file mode 100644 index 0000000..c6102fc --- /dev/null +++ b/moralesty1/ping.c @@ -0,0 +1,1175 @@ +/* +* Copyright (c) 1989 The Regents of the University of California. +* All rights reserved. +* +* This code is derived from software contributed to Berkeley by +* Mike Muuss. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. All advertising materials mentioning features or use of this software +* must display the following acknowledgement: +* This product includes software developed by the University of +* California, Berkeley and its contributors. +* 4. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n" +"All rights reserved.\n"; +/* +* From: @(#)ping.c 5.9 (Berkeley) 5/12/91 +*/ +char rcsid[] = "$Id: ping.c,v 1.22 1997/06/08 19:39:47 dholland Exp $"; +char pkg[] = "netkit-base-0.10"; + +/* +* P I N G . C +* +* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, +* measure round-trip-delays and packet loss across network paths. +* +* Author - +* Mike Muuss +* U. S. Army Ballistic Research Laboratory +* December, 1983 +* +* Status - +* Public Domain. Distribution Unlimited. +* Bugs - +* More statistics could always be gathered. +* This program has to run SUID to ROOT to access the ICMP socket. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* Note: on some systems dropping root makes the process dumpable or +* traceable. In that case if you enable dropping root and someone +* traces ping, they get control of a raw socket and can start +* spoofing whatever packets they like. SO BE CAREFUL. +*/ +#ifdef __linux__ +#define SAFE_TO_DROP_ROOT +#endif + +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +#define icmphdr icmp +#define ICMP_DEST_UNREACH ICMP_UNREACH +#define ICMP_NET_UNREACH ICMP_UNREACH_NET +#define ICMP_HOST_UNREACH ICMP_UNREACH_HOST +#define ICMP_PORT_UNREACH ICMP_UNREACH_PORT +#define ICMP_PROT_UNREACH ICMP_UNREACH_PROTOCOL +#define ICMP_FRAG_NEEDED ICMP_UNREACH_NEEDFRAG +#define ICMP_SR_FAILED ICMP_UNREACH_SRCFAIL +#define ICMP_NET_UNKNOWN ICMP_UNREACH_NET_UNKNOWN +#define ICMP_HOST_UNKNOWN ICMP_UNREACH_HOST_UNKNOWN +#define ICMP_HOST_ISOLATED ICMP_UNREACH_ISOLATED +#define ICMP_NET_UNR_TOS ICMP_UNREACH_TOSNET +#define ICMP_HOST_UNR_TOS ICMP_UNREACH_TOSHOST +#define ICMP_SOURCE_QUENCH ICMP_SOURCEQUENCH +#define ICMP_REDIR_NET ICMP_REDIRECT_NET +#define ICMP_REDIR_HOST ICMP_REDIRECT_HOST +#define ICMP_REDIR_NETTOS ICMP_REDIRECT_TOSNET +#define ICMP_REDIR_HOSTTOS ICMP_REDIRECT_TOSHOST +#define ICMP_TIME_EXCEEDED ICMP_TIMXCEED +#define ICMP_EXC_TTL ICMP_TIMXCEED_INTRANS +#define ICMP_EXC_FRAGTIME ICMP_TIMXCEED_REASS +#define ICMP_PARAMETERPROB ICMP_PARAMPROB +#define ICMP_TIMESTAMP ICMP_TSTAMP +#define ICMP_TIMESTAMPREPLY ICMP_TSTAMPREPLY +#define ICMP_INFO_REQUEST ICMP_IREQ +#define ICMP_INFO_REPLY ICMP_IREQREPLY +#else +#define ICMP_MINLEN 28 +#define inet_ntoa(x) inet_ntoa(*((struct in_addr *)&(x))) +#endif + + +#define DEFDATALEN (64 - 8) /* default data length */ +#define MAXIPLEN 60 +#define MAXICMPLEN 76 +#define MAXPACKET (65536 - 60 - 8)/* max packet size */ +#define MAXWAIT 10 /* max seconds to wait for response */ +#define NROUTES 9 /* number of record route slots */ + +#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)) + +/* various options */ +int options; +#define F_FLOOD 0x001 +#define F_INTERVAL 0x002 +#define F_NUMERIC 0x004 +#define F_PINGFILLED 0x008 +#define F_QUIET 0x010 +#define F_RROUTE 0x020 +#define F_SO_DEBUG 0x040 +#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 +* to 8192 for complete accuracy... +*/ +#define MAX_DUP_CHK (8 * 128) +int mx_dup_ck = MAX_DUP_CHK; +char rcvd_tbl[MAX_DUP_CHK / 8]; + +struct sockaddr whereto; /* who to ping */ +int datalen = DEFDATALEN; +int s; /* socket file descriptor */ +u_char outpack[MAXPACKET]; +char BSPACE = '\b'; /* characters written for flood */ +char DOT = '.'; +static char *hostname; +static int ident; /* process id to identify our packets */ + + + +/* timing */ +static int timing; /* flag to do timing */ +static long tmin = LONG_MAX; /* minimum round trip time */ +static long tmax = 0; /* maximum round trip time */ +static u_long tsum; /* sum of all times, for doing average */ + + + + +int +main(int argc, char *argv[]) +{ + struct timeval timeout; + struct hostent *hp; + struct sockaddr_in *to; + struct protoent *proto; + struct in_addr ifaddr; + int i; + int ch, fdmask, hold, packlen, preload; + u_char *datap, *packet; + char *target, hnamebuf[MAXHOSTNAMELEN]; + u_char ttl, loop; + int am_i_root; + #ifdef IP_OPTIONS + char rspace[3 + 4 * NROUTES + 1]; /* record route space */ + #endif + + static char *null = NULL; + __environ = &null; + am_i_root = (getuid()==0); + + /* + * Pull this stuff up front so we can drop root if desired. + */ + if (!(proto = getprotobyname("icmp"))) { + (void)fprintf(stderr, "ping: unknown protocol icmp.\n"); + exit(2); + } + if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { + if (errno==EPERM) { + fprintf(stderr, "ping: ping must run as root\n"); + } + else perror("ping: socket"); + exit(2); + } + + #ifdef SAFE_TO_DROP_ROOT + setuid(getuid()); + #endif + + preload = 0; + datap = &outpack[8 + sizeof(struct timeval)]; + while ((ch = getopt(argc, argv, "I:LRc:dfh:i:l:np:qrs:t:v")) != EOF) + switch(ch) { + case 'c': + npackets = atoi(optarg); + if (npackets <= 0) { + (void)fprintf(stderr, + "ping: bad number of packets to transmit.\n"); + exit(2); + } + break; + case 'd': + options |= F_SO_DEBUG; + break; + case 'f': + if (!am_i_root) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(2); + } + options |= F_FLOOD; + setbuf(stdout, NULL); + break; + case 'i': /* wait between sending packets */ + interval = atoi(optarg); + if (interval <= 0) { + (void)fprintf(stderr, + "ping: bad timing interval.\n"); + exit(2); + } + options |= F_INTERVAL; + break; + case 'l': + if (!am_i_root) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(2); + } + preload = atoi(optarg); + if (preload < 0) { + (void)fprintf(stderr, + "ping: bad preload value.\n"); + exit(2); + } + break; + case 'n': + options |= F_NUMERIC; + break; + case 'p': /* fill buffer with user pattern */ + options |= F_PINGFILLED; + fill(datap, optarg); + break; + case 'q': + options |= F_QUIET; + break; + case 'R': + options |= F_RROUTE; + break; + case 'r': + options |= F_SO_DONTROUTE; + break; + case 's': /* size of packet to send */ + datalen = atoi(optarg); + if (datalen > MAXPACKET) { + (void)fprintf(stderr, + "ping: packet size too large.\n"); + exit(2); + } + if (datalen <= 0) { + (void)fprintf(stderr, + "ping: illegal packet size.\n"); + exit(2); + } + break; + 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(2); + } + ttl = i; + break; + case 'I': + moptions |= MULTICAST_IF; + { + int i1, i2, i3, i4; + char junk; + + if (sscanf(optarg, "%u.%u.%u.%u%c", + &i1, &i2, &i3, &i4, &junk) != 4) { + printf("bad interface address '%s'\n", + optarg); + exit(2); + } + 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; + + memset(&whereto, 0, sizeof(struct sockaddr)); + to = (struct sockaddr_in *)&whereto; + to->sin_family = AF_INET; + if (inet_aton(target, &to->sin_addr)) { + hostname = target; + } + else { + hp = gethostbyname(target); + if (!hp) { + (void)fprintf(stderr, + "ping: unknown host %s\n", target); + exit(2); + } + to->sin_family = hp->h_addrtype; + if (hp->h_length > (int)sizeof(to->sin_addr)) { + hp->h_length = sizeof(to->sin_addr); + } + memcpy(&to->sin_addr, hp->h_addr, hp->h_length); + (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); + hostname = hnamebuf; + } + + if (options & F_FLOOD && options & F_INTERVAL) { + (void)fprintf(stderr, + "ping: -f and -i incompatible options.\n"); + exit(2); + } + + if (datalen >= (int)sizeof(struct timeval)) /* can we time transfer */ + timing = 1; + packlen = datalen + MAXIPLEN + MAXICMPLEN; + packet = malloc((u_int)packlen); + if (!packet) { + (void)fprintf(stderr, "ping: out of memory.\n"); + exit(2); + } + if (!(options & F_PINGFILLED)) + for (i = 8; i < datalen; ++i) + *datap++ = i; + + ident = getpid() & 0xFFFF; + hold = 1; + + if (options & F_SO_DEBUG) + (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, + sizeof(hold)); + + if (options & F_SO_DONTROUTE) + (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, + sizeof(hold)); + + /* this is necessary for broadcast pings to work */ + setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&hold, sizeof(hold)); + + /* record route option */ + if (options & F_RROUTE) { + #ifdef IP_OPTIONS + memset(rspace, 0, sizeof(rspace)); + rspace[IPOPT_OPTVAL] = IPOPT_RR; + rspace[IPOPT_OLEN] = sizeof(rspace)-1; + rspace[IPOPT_OFFSET] = IPOPT_MINOFF; + if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, + sizeof(rspace)) < 0) { + perror("ping: record route"); + exit(2); + } + #else + (void)fprintf(stderr, + "ping: record route not available in this implementation.\n"); + exit(2); + #endif /* IP_OPTIONS */ + } + + /* + * When pinging the broadcast address, you can get a lot of answers. + * Doing something so evil is useful if you are trying to stress the + * ethernet, or just want to fill the arp cache to get some stuff for + * /etc/ethers. + */ + hold = 48 * 1024; + (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, + sizeof(hold)); + + /*#if 0*/ + 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); + } + } + /*#endif*/ + + 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), + datalen); + else + (void)printf("PING %s: %d data bytes\n", hostname, datalen); + + (void)signal(SIGINT, finish); + (void)signal(SIGALRM, catcher); + + while (preload--) /* fire off them quickies */ + pinger(); + + if ((options & F_FLOOD) == 0) + catcher(0); /* start things going */ + + for (;;) { + struct sockaddr_in from; + register int cc; + size_t fromlen; + + if (options & F_FLOOD) { + pinger(); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + fdmask = 1 << s; + if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout) < 1) + continue; + } + fromlen = sizeof(from); + if ((cc = recvfrom(s, (char *)packet, packlen, 0, + (struct sockaddr *)&from, &fromlen)) < 0) { + if (errno == EINTR) + continue; + perror("ping: recvfrom"); + continue; + } + pr_pack((char *)packet, cc, &from); + if (npackets && nreceived >= npackets) + break; + } + finish(0); + /* NOTREACHED */ + return 0; + } + + /* + * catcher -- + * This routine causes another PING to be transmitted, and then + * schedules another SIGALRM for 1 second from now. + * + * bug -- + * Our sense of time will slowly skew (i.e., packets will not be + * launched exactly at 1-second intervals). This does not affect the + * quality of the delay and loss statistics. + */ + static void + catcher(int ignore) + { + int waittime; + + (void)ignore; + pinger(); + (void)signal(SIGALRM, catcher); + if (!npackets || ntransmitted < npackets) + alarm((u_int)interval); + else { + if (nreceived) { + waittime = 2 * tmax / 1000; + if (!waittime) + waittime = 1; + if (waittime > MAXWAIT) + waittime = MAXWAIT; + } else + waittime = MAXWAIT; + (void)signal(SIGALRM, finish); + (void)alarm((u_int)waittime); + } + } + + #if !defined(__GLIBC__) || (__GLIBC__ < 2) + #define icmp_type type + #define icmp_code code + #define icmp_cksum checksum + #define icmp_id un.echo.id + #define icmp_seq un.echo.sequence + #define icmp_gwaddr un.gateway + #endif /* __GLIBC__ */ + + #define ip_hl ihl + #define ip_v version + #define ip_tos tos + #define ip_len tot_len + #define ip_id id + #define ip_off frag_off + #define ip_ttl ttl + #define ip_p protocol + #define ip_sum check + #define ip_src saddr + #define ip_dst daddr + + /* + * pinger -- + * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an ascending integer. The first 8 bytes + * of the data portion are used to hold a UNIX "timeval" struct in VAX + * byte-order, to compute the round-trip time. + */ + static void + pinger(void) + { + register struct icmphdr *icp; + register int cc; + int i; + + icp = (struct icmphdr *)outpack; + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = ntransmitted++; + icp->icmp_id = ident; /* ID */ + + CLR(icp->icmp_seq % mx_dup_ck); + + if (timing) + (void)gettimeofday((struct timeval *)&outpack[8], + (struct timezone *)NULL); + + cc = datalen + 8; /* skips ICMP portion */ + + /* compute ICMP checksum here */ + icp->icmp_cksum = in_cksum((u_short *)icp, cc); + + i = sendto(s, (char *)outpack, cc, 0, &whereto, + sizeof(struct sockaddr)); + + if (i < 0 || i != cc) { + if (i < 0) + perror("ping: sendto"); + (void)printf("ping: wrote %s %d chars, ret=%d\n", + hostname, cc, i); + } + if (!(options & F_QUIET) && options & F_FLOOD) + (void)write(STDOUT_FILENO, &DOT, 1); + } + + /* + * pr_pack -- + * Print out the packet, if it came from us. This logic is necessary + * because ALL readers of the ICMP socket get a copy of ALL ICMP packets + * which arrive ('tis only fair). This permits multiple copies of this + * program to be run without having intermingled output (or statistics!). + */ + void + pr_pack(char *buf, int cc, struct sockaddr_in *from) + { + register struct icmphdr *icp; + register int i; + register u_char *cp,*dp; + /*#if 0*/ + register u_long l; + register int j; + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; + /*#endif*/ + struct iphdr *ip; + struct timeval tv, *tp; + long triptime = 0; + int hlen, dupflag; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + + /* Check the IP header */ + ip = (struct iphdr *)buf; + hlen = ip->ip_hl << 2; + if (cc < datalen + ICMP_MINLEN) { + if (options & F_VERBOSE) + (void)fprintf(stderr, + "ping: packet too short (%d bytes) from %s\n", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr)); + return; + } + + /* Now the ICMP part */ + cc -= hlen; + icp = (struct icmphdr *)(buf + hlen); + if (icp->icmp_type == ICMP_ECHOREPLY) { + if (icp->icmp_id != ident) + return; /* 'Twas not our ECHO */ + ++nreceived; + if (timing) { + #ifndef icmp_data + tp = (struct timeval *)(icp + 1); + #else + tp = (struct timeval *)icp->icmp_data; + #endif + tvsub(&tv, tp); + triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); + tsum += triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } + + if (TST(icp->icmp_seq % mx_dup_ck)) { + ++nrepeats; + --nreceived; + dupflag = 1; + } else { + SET(icp->icmp_seq % mx_dup_ck); + dupflag = 0; + } + + if (options & F_QUIET) + return; + + if (options & F_FLOOD) + (void)write(STDOUT_FILENO, &BSPACE, 1); + else { + (void)printf("%d bytes from %s: icmp_seq=%u", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), + icp->icmp_seq); + (void)printf(" ttl=%d", ip->ip_ttl); + if (timing) + (void)printf(" time=%ld.%ld ms", triptime/10, + triptime%10); + if (dupflag) + (void)printf(" (DUP!)"); + /* check the data */ + #ifndef icmp_data + cp = ((u_char*)(icp + 1) + 8); + #else + cp = (u_char*)icp->icmp_data + 8; + #endif + dp = &outpack[8 + sizeof(struct timeval)]; + for (i = 8; i < datalen; ++i, ++cp, ++dp) { + if (*cp != *dp) { + (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", + i, *dp, *cp); + cp = (u_char*)(icp + 1); + for (i = 8; i < datalen; ++i, ++cp) { + if ((i % 32) == 8) + (void)printf("\n\t"); + (void)printf("%x ", *cp); + } + break; + } + } + } + } else { + /* We've got something other than an ECHOREPLY */ + if (!(options & F_VERBOSE)) + return; + (void)printf("%d bytes from %s: ", cc, + pr_addr(from->sin_addr.s_addr)); + pr_icmph(icp); + } + + /*#if 0*/ + /* Display any IP options */ + cp = (u_char *)buf + sizeof(struct iphdr); + + for (; hlen > (int)sizeof(struct iphdr); --hlen, ++cp) + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + (void)printf("\nLSRR: "); + hlen -= 2; + j = *++cp; + ++cp; + if (j > IPOPT_MINOFF) + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + j -= 4; + if (j <= IPOPT_MINOFF) + break; + (void)putchar('\n'); + } + break; + case IPOPT_RR: + j = *++cp; /* get length */ + i = *++cp; /* and pointer */ + hlen -= 2; + if (i > j) + i = j; + i -= IPOPT_MINOFF; + if (i <= 0) + continue; + if (i == old_rrlen + && cp == (u_char *)buf + sizeof(struct iphdr) + 2 + && !memcmp((char *)cp, old_rr, i) + && !(options & F_FLOOD)) { + (void)printf("\t(same route)"); + i = ((i + 3) / 4) * 4; + hlen -= i; + cp += i; + break; + } + old_rrlen = i; + memcpy(old_rr, cp, i); + (void)printf("\nRR: "); + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + i -= 4; + if (i <= 0) + break; + (void)putchar('\n'); + } + break; + case IPOPT_NOP: + (void)printf("\nNOP"); + break; + default: + (void)printf("\nunknown option %x", *cp); + break; + } + /*#endif*/ + if (!(options & F_FLOOD)) { + (void)putchar('\n'); + (void)fflush(stdout); + } + } + + /* + * in_cksum -- + * Checksum routine for Internet Protocol family headers (C Version) + */ + static int + in_cksum(u_short *addr, int len) + { + register int nleft = len; + register u_short *w = addr; + register int sum = 0; + u_short answer = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + *(u_char *)(&answer) = *(u_char *)w ; + sum += answer; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return(answer); + } + + /* + * tvsub -- + * Subtract 2 timeval structs: out = out - in. Out is assumed to + * be >= in. + */ + static void + tvsub(register struct timeval *out, register struct timeval *in) + { + if ((out->tv_usec -= in->tv_usec) < 0) { + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; + } + + /* + * finish -- + * Print out statistics, and give up. + */ + static void + finish(int ignore) + { + (void)ignore; + + (void)signal(SIGINT, SIG_IGN); + (void)putchar('\n'); + (void)fflush(stdout); + (void)printf("--- %s ping statistics ---\n", hostname); + (void)printf("%ld packets transmitted, ", ntransmitted); + (void)printf("%ld packets received, ", nreceived); + if (nrepeats) + (void)printf("+%ld duplicates, ", nrepeats); + if (ntransmitted) + if (nreceived > ntransmitted) + (void)printf("-- somebody's printing up packets!"); + else + (void)printf("%d%% packet loss", + (int) (((ntransmitted - nreceived) * 100) / + ntransmitted)); + (void)putchar('\n'); + if (nreceived && timing) + (void)printf("round-trip min/avg/max = %ld.%ld/%lu.%ld/%ld.%ld ms\n", + tmin/10, tmin%10, + (tsum / (nreceived + nrepeats))/10, + (tsum / (nreceived + nrepeats))%10, + tmax/10, tmax%10); + + if (nreceived==0) exit(1); + exit(0); + } + + #ifdef notdef + static char *ttab[] = { + "Echo Reply", /* ip + seq + udata */ + "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ + "Source Quench", /* IP */ + "Redirect", /* redirect type, gateway, + IP */ + "Echo", + "Time Exceeded", /* transit, frag reassem + IP */ + "Parameter Problem", /* pointer + IP */ + "Timestamp", /* id + seq + three timestamps */ + "Timestamp Reply", /* " */ + "Info Request", /* id + sq */ + "Info Reply" /* " */ + }; + #endif + + /* + * pr_icmph -- + * Print a descriptive string about an ICMP header. + */ + static void + pr_icmph(struct icmphdr *icp) + { + switch(icp->icmp_type) { + case ICMP_ECHOREPLY: + (void)printf("Echo Reply\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_DEST_UNREACH: + switch(icp->icmp_code) { + case ICMP_NET_UNREACH: + (void)printf("Destination Net Unreachable\n"); + break; + case ICMP_HOST_UNREACH: + (void)printf("Destination Host Unreachable\n"); + break; + case ICMP_PROT_UNREACH: + (void)printf("Destination Protocol Unreachable\n"); + break; + case ICMP_PORT_UNREACH: + (void)printf("Destination Port Unreachable\n"); + break; + case ICMP_FRAG_NEEDED: + (void)printf("frag needed and DF set\n"); + break; + case ICMP_SR_FAILED: + (void)printf("Source Route Failed\n"); + break; + case ICMP_NET_UNKNOWN: + (void)printf("Network Unknown\n"); + break; + case ICMP_HOST_UNKNOWN: + (void)printf("Host Unknown\n"); + break; + case ICMP_HOST_ISOLATED: + (void)printf("Host Isolated\n"); + break; + case ICMP_NET_UNR_TOS: + printf("Destination Network Unreachable At This TOS\n"); + break; + case ICMP_HOST_UNR_TOS: + printf("Destination Host Unreachable At This TOS\n"); + break; + #ifdef ICMP_PKT_FILTERED + case ICMP_PKT_FILTERED: + (void)printf("Packet Filtered\n"); + break; + #endif + #ifdef ICMP_PREC_VIOLATION + case ICMP_PREC_VIOLATION: + (void)printf("Precedence Violation\n"); + break; + #endif + #ifdef ICMP_PREC_CUTOFF + case ICMP_PREC_CUTOFF: + (void)printf("Precedence Cutoff\n"); + break; + #endif + default: + (void)printf("Dest Unreachable, Unknown Code: %d\n", + icp->icmp_code); + break; + } + /* Print returned IP header information */ + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_SOURCE_QUENCH: + (void)printf("Source Quench\n"); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_REDIRECT: + switch(icp->icmp_code) { + case ICMP_REDIR_NET: + (void)printf("Redirect Network"); + break; + case ICMP_REDIR_HOST: + (void)printf("Redirect Host"); + break; + case ICMP_REDIR_NETTOS: + (void)printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIR_HOSTTOS: + (void)printf("Redirect Type of Service and Host"); + break; + default: + (void)printf("Redirect, Bad Code: %d", icp->icmp_code); + break; + } + (void)printf("(New addr: %s)\n", + inet_ntoa(icp->icmp_gwaddr)); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_ECHO: + (void)printf("Echo Request\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_TIME_EXCEEDED: + switch(icp->icmp_code) { + case ICMP_EXC_TTL: + (void)printf("Time to live exceeded\n"); + break; + case ICMP_EXC_FRAGTIME: + (void)printf("Frag reassembly time exceeded\n"); + break; + default: + (void)printf("Time exceeded, Bad Code: %d\n", + icp->icmp_code); + break; + } + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_PARAMETERPROB: + (void)printf("Parameter problem: IP address = %s\n", + inet_ntoa (icp->icmp_gwaddr)); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_TIMESTAMP: + (void)printf("Timestamp\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_TIMESTAMPREPLY: + (void)printf("Timestamp Reply\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_INFO_REQUEST: + (void)printf("Information Request\n"); + /* XXX ID + Seq */ + break; + case ICMP_INFO_REPLY: + (void)printf("Information Reply\n"); + /* XXX ID + Seq */ + break; + #ifdef ICMP_MASKREQ + case ICMP_MASKREQ: + (void)printf("Address Mask Request\n"); + break; + #endif + #ifdef ICMP_MASKREPLY + case ICMP_MASKREPLY: + (void)printf("Address Mask Reply\n"); + break; + #endif + default: + (void)printf("Bad ICMP type: %d\n", icp->icmp_type); + } + } + + /* + * pr_iph -- + * Print an IP header with options. + */ + static void + pr_iph(struct iphdr *ip) + { + int hlen; + u_char *cp; + + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + 20; /* point to options */ + + (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); + (void)printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); + (void)printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, + (ip->ip_off) & 0x1fff); + (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); + (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_src))); + (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_dst))); + /* dump and option bytes */ + while (hlen-- > 20) { + (void)printf("%02x", *cp++); + } + (void)putchar('\n'); + } + + /* + * pr_addr -- + * Return an ascii host address as a dotted quad and optionally with + * a hostname. + */ + static char * + pr_addr(u_long l) + { + struct hostent *hp; + static char buf[256]; + + if ((options & F_NUMERIC) || + !(hp = gethostbyaddr((char *)&l, 4, AF_INET))) + (void)snprintf(buf, sizeof(buf), "%s", + inet_ntoa(*(struct in_addr *)&l)); + else + (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, + inet_ntoa(*(struct in_addr *)&l)); + return(buf); + } + + /* + * pr_retip -- + * Dump some info on a returned (via ICMP) IP packet. + */ + static void + pr_retip(struct iphdr *ip) + { + int hlen; + u_char *cp; + + pr_iph(ip); + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + hlen; + + if (ip->ip_p == 6) + (void)printf("TCP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + else if (ip->ip_p == 17) + (void)printf("UDP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + } + + static void + fill(void *bp1, char *patp) + { + register int ii, jj, kk; + int pat[16]; + char *cp, *bp = (char *)bp1; + + for (cp = patp; *cp; cp++) + if (!isxdigit(*cp)) { + (void)fprintf(stderr, + "ping: patterns must be specified as hex digits.\n"); + exit(2); + } + ii = sscanf(patp, + "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", + &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], + &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], + &pat[13], &pat[14], &pat[15]); + + if (ii > 0) + for (kk = 0; kk <= MAXPACKET - (8 + ii); kk += ii) + for (jj = 0; jj < ii; ++jj) + bp[jj + kk] = pat[jj]; + if (!(options & F_QUIET)) { + (void)printf("PATTERN: 0x"); + for (jj = 0; jj < ii; ++jj) + (void)printf("%02x", bp[jj] & 0xFF); + (void)printf("\n"); + } + } + + static void + usage(void) + { + (void)fprintf(stderr, + "usage: ping [-LRdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] [-t ttl] [-I interface address] host\n"); + exit(2); + } diff --git a/moralesty1/pong.cpp b/moralesty1/pong.cpp new file mode 100644 index 0000000..33ef7ee --- /dev/null +++ b/moralesty1/pong.cpp @@ -0,0 +1,968 @@ +/* + +Pong + +Using the Internet Control Message Protocol (ICMP) ECHO_REQUEST +and ECHO_REPLY messages to measure round-trip-delays and packet +loss across network paths. Eventually, we'd like to expand +this to UDP pinging as well. + +Created as a 2013 NDSU Capstone Project with specifications +and requirements provided by Ericsson. + +An extension/reimplementation of the original ping.c for the 21st +century. +Emphasis is on readability and ease of understanding the code. +Inspiration and design inspired by: + +Mike Muuss +U. S. Army Ballistic Research Laboratory +December, 1983 +Modified at UC Berkeley + +*/ + + +/* + +Imports and definitions + +*/ + +#define IP_MINLENGTH 34 +#define ICMP_MINLENGTH 16 +#define DEFAULT_LISTEN_TIMEOUT 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __MACH__ +#include +#include +#endif + +#if __unix__||__APPLE__ +#include +#include +#include +#include +#include +#include +#include +#include + +#elif WIN32 +#include +#include +struct sockaddr_in *socketAddress; +/* ICMP Header for Windows branch */ +struct icmp { + BYTE icmp_type; // ICMP packet type + BYTE icmp_code; // Type sub code + USHORT icmp_cksum; + USHORT icmp_id; + USHORT icmp_seq; + ULONG icmp_data; // not part of ICMP, but we need it +}; +#endif + +/* + +Initialize Structs + +*/ + +struct sockaddr_in *whereto; +struct in_addr destIP; +struct in_addr srcIP; +struct icmp * icmpHeader; +struct icmp * receivedICMPHeader; +struct icmp * receivedIPHeader; +struct ip * ipHeader; +u_char * packet[100]; +u_char * packetIP[100]; + +/* + +Global Variables for stats and keeping track +of how many pings were sent, how many need +to be excluded, and more. + +*/ +int sent; +int packetsTimedOut = 0; +int processID; +int icmpPayloadLength = 30; +int pingsToSend = 5; +int pingsSent = 0; +int pingsToExclude = 0; +double totalResponseTime = 0.0; +double sumOfResponseTimesSquared = 0.0; +double roundTripTime = 0.0; +int pingsReceived = 0; +bool excludingPing; +int timeoutInput = DEFAULT_LISTEN_TIMEOUT; +volatile bool killSwitch = true; + + + + + +/* + +Checksum() + +Simple checksum function for ICMP Header. This implentation was +adapted from Mike Musss' version of ping.c + +*/ +static u_short checksum(u_short *ICMPHeader, int len) +{ + register int nleft = len; + register u_short *ICMPPointer = ICMPHeader; + register int sum = 0; + u_short answer = 0; + + /* + Our algorithm is simple, using a 32 bit accumulator (sum), we add + sequential 16 bit words to it, and at the end, fold back all the + carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) + { + sum += *ICMPPointer; + ICMPPointer++; + nleft -= 2; + } + + /* Mop up an odd byte, if necessary */ + if (nleft == 1) + { + *(u_char *)(&answer) = *(u_char *) ICMPPointer; + sum += answer; + } + + /* Add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = (u_short)~sum; /* truncate to 16 bits */ + return(answer); +} + +/* + +pingICMP() + +This method actually sends our ECHO_REQUEST across the internet. +It computes the ICMP checksum and sends the packet to the address +specified in main(). + +*/ +void pingICMP(int socketDescriptor, int icmpPayloadLength) +{ + /* Get time, put it in the packet */ + + /* Set time sent */ + #ifdef __MACH__ + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, (mach_timespec_t *)icmpHeader->icmp_data); + mach_port_deallocate(mach_task_self(), cclock); + + #elif __WINDOWS__ + // GetTick64Count() + #elif __GNUC__ + clock_gettime(CLOCK_MONOTONIC, (struct timespec *)icmpHeader->icmp_data); + #else + //clock_gettime(CLOCK_REALTIME, &ts); + #endif + + /* Compute checksum */ + icmpHeader->icmp_cksum = 0; + icmpHeader->icmp_cksum = checksum((u_short *)icmpHeader, sizeof(*icmpHeader)); + + /* Try to send the packet */ + sent = sendto(socketDescriptor, packet, icmpPayloadLength + 8, 0, (struct sockaddr *)whereto, sizeof(struct sockaddr)); + + /* Check if the packet sent or not */ + if(sent > 0) + { + pingsSent++; + /* Increment the packet sequence number */ + icmpHeader->icmp_seq++; + } + else + { + printf("Ping not sent.\n\n"); + } +} + +/* + +report() + +This function reports the final statistics, either to the command line +or to a CSV (comma separated value) file. Current statistics and output +information includes pings sent, pings received, pings dropped, pings excluded, +average response time, and standard deviation for response time. + +*/ +void report() +{ + if(pingsSent != 0) + { + printf("----------------------------------------------------------------\n"); + printf("%d packets sent, %d dropped", pingsSent, (pingsSent - pingsReceived)); + if(excludingPing) + { + printf(", %d excluded from summary\n", pingsToExclude); + } + else + { + printf("\n"); + } + double average = totalResponseTime / (pingsSent - pingsToExclude); + printf("Stats avg/stddev : %f / %f\n", average, sqrt((sumOfResponseTimesSquared / (pingsReceived - pingsToExclude)) - (average * average))); + printf("----------------------------------------------------------------\n"); + } +} + +/* + +listenICMP() + +This function waits from an incoming packet, checks to see if it is our ECHO_REPLY, +and then gets data out of the packet and computes statistics or doesn't (depending +on if we're excluding that response or not). + +*/ +void listenICMP(int socketDescriptor, sockaddr_in * fromWhom, bool quiet, bool excludingPings, int timeoutLength) +{ + /* Setting some variables needed for select() and our file descriptor */ + char receivedPacketBuffer[512]; + fd_set readfds; + FD_SET(socketDescriptor, &readfds); + struct timeval timeout; + timeout.tv_sec = timeoutLength; // timeout period, seconds (added second, if that matters) + //printf("Timeout length") + timeout.tv_usec = 0; // timeuot period, microseconds 1,000,000 micro = second + // TODO Make this timeout dependent on how many pings have been sent... + int selectStatus = select(socketDescriptor+1, &readfds, NULL, NULL, &timeout); + socklen_t fromWhomLength = sizeof(fromWhom); + if(selectStatus == -1) + { + printf("LISTEN: Error in select()\n"); + } + else if(selectStatus == 0) + { + printf("I'm tired of waiting. Timeout.\n"); + packetsTimedOut++; + csvOutput << "Dropped" << endl; + return; + } + else + { + if(FD_ISSET(socketDescriptor, &readfds)) + { + + /* Receive the data */ + ssize_t bytesReceived = recvfrom(socketDescriptor, receivedPacketBuffer, sizeof(receivedPacketBuffer), 0, (struct sockaddr *)&fromWhom, &fromWhomLength); + + /* Format the received data into the IP struct, then shift bits */ + struct ip * receivedIPHeader = (struct ip *) receivedPacketBuffer; + int headerLength = receivedIPHeader->ip_hl << 2; + + /* Format the received data into the ICMP struct */ + receivedICMPHeader = (struct icmp *)(receivedPacketBuffer + headerLength); + + /* Get the time */ + #if __MACH__ + clock_get_time(cclock, &receivedTime); + mach_timespec_t * sentTime = (mach_timespec_t *)receivedICMPHeader->icmp_data; + /* Thanks Richard Stevens' book UNIX Network Programming for helping with + this next chunk of time processing code */ + if ( (receivedTime.tv_nsec -= sentTime->tv_nsec) < 0) + { + --receivedTime.tv_sec; + receivedTime.tv_nsec += 1000000000; + } + + #elif __WINDOWS__ + // GetTick64Count() + #elif __GNUC__ + clock_gettime(CLOCK_MONOTONIC, &receivedTime2); + struct timespec * sentTime2 = (struct timespec *)receivedICMPHeader->icmp_data; + /* Thanks Richard Stevens' book UNIX Network Programming for helping with + this next chunk of time processing code */ + if ( (receivedTime2.tv_nsec -= sentTime2->tv_nsec) < 0) + { + --receivedTime2.tv_sec; + receivedTime2.tv_nsec += 1000000000; + } + + #endif + + /* Check if the packet was an ECHO_REPLY, and if it was meant for our computer using the ICMP id, + which we set to the process ID */ + if (receivedICMPHeader->icmp_type == 0) + { + + if(receivedICMPHeader->icmp_id != processID) + { + printf("Not our packet\n"); + printf("processID = %d \t ID = %d\n", processID, receivedICMPHeader->icmp_id); + } + else + { + /* We got a valid reply. Count it! */ + pingsReceived++; + + /* Calculate round trip time */ + if(!excludingPings) + { + #if __MACH__ + receivedTime.tv_sec -= sentTime->tv_sec; + roundTripTime = receivedTime.tv_sec * 1000.0 + receivedTime.tv_nsec / 1000000.0; + #elif __GNUC__ + receivedTime2.tv_sec -= sentTime2->tv_sec; + roundTripTime = receivedTime2.tv_sec * 1000.0 + receivedTime2.tv_nsec / 1000000.0; + #endif + sumOfResponseTimesSquared += roundTripTime * roundTripTime; + totalResponseTime += roundTripTime; + } + + /* Get presentation format of source IP */ + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(receivedIPHeader->ip_src), str, INET_ADDRSTRLEN); + + /* If we're counting stats for this reply, add data to running stats */ + if(!excludingPings) + { + /* If we're in CSV mode, print info to the file instead of to the terminal */ + if(quiet) + { + printf(".\n"); + csvOutput << (bytesReceived + 14) << "," << str << "," << receivedICMPHeader->icmp_seq << "," << (int)receivedIPHeader->ip_ttl << "," << roundTripTime << endl; + } + /* Otherwise, print received reply information to the terminal */ + else + { + printf("%d bytes from %s packet number:%d ttl:%d time:%f ms\n", (bytesReceived + 14), str, receivedICMPHeader->icmp_seq, (int)receivedIPHeader->ip_ttl, roundTripTime); + } + } + } + } + } + } +} + + +/* + +buildPing() + +buildPing() initializes the ICMP Header and IP Header structs, which +contain essential packet information. The IP address information is +set in main(). + +*/ +void buildPing() +{ + icmpHeader = (struct icmp *) packet; + ipHeader= (struct ip *) packetIP; + icmpHeader->icmp_type = 8; // This shouldn't change + icmpHeader->icmp_code = 0; + icmpHeader->icmp_cksum = 0; + icmpHeader->icmp_seq = 1; + icmpHeader->icmp_id = processID; + ipHeader->ip_p = 1; + ipHeader->ip_ttl = 64; //Recommended value, according to the internet. + ipHeader->ip_hl = 5; +} + + +void interrupt(int signal); +/* + +main() + +Where the magic happens. Command line flags are set, program +control is set. + +*/ +char *argv[2]; +int main(int argc, const char** argv) +{ + signal(SIGINT, interrupt); + #ifdef WIN32 + WSADATA wsaData; + int result=WSAStartup(MAKEWORD(2,0), &wsaData); + if(result != 0) { + printf("WSAStartup failed with error: %d\n", wsaData); + return 1; + #endif + printf("----------------------------------------------------------------\n"); + + int socketDescriptor; + + /* + + Variables for command line flag processing + + */ + const char* destination = argv[1]; + bool timeBetweenReq = 0; // -q // --request-time + float msecsBetweenReq = 1000; + bool timeBetweenRepReq = 0; // -b // --reply-request-time + int msecsBetweenRepReq = 0; + bool datagramSizeSet = 0; // -d // --datagram-size + bool payloadSize = 0; // -p // --payload-size + bool randSizeMinMax = 0; // -l // --random-size-minmax + int bytesSizeMin = 0; + int bytesSizeMax = 0; + bool randSizeAvgStd = 0; // -r // --random-size-avgstd + int bytesSizeAvg = 0; + int bytesSizeStd = 0; + bool randTimeMinMax = 0; // -s // --random-time-minmax + int msecsTimeMin = 0; + int msecsTimeMax = 0; + bool randTimeAvgStd = 0; // -t // --random-time-avgstd + int msecsTimeAvg = 0; + int msecsTimeStd = 0; + bool increasingSize = 0; // -i // --increasing-size + int sizeInitial = 0; // Must be greater than or equal to (IP_MINLENGTH + ICMP_MINLENGTH) + int sizeGrowth = 0; + excludingPing = 0; // -e // --exclud + bool multiplePings = 0; // -n // --ping-count + bool csvMode = 0; // -c // --csv + + if(argc - 1 == 0) + { + printf("USAGE:\nePing [host IP or domain name]\n[-n/--pings-to-send num of pings to send]\n[-e/--exclude num of pings to exclude from stats]\n\nTIME\n[-q/--request-time time between sent pings]\n[-t/--random-time-avgstd set random, normally distributed time between pings - enter average and standard deviation]\n[-z/--timeout manually set timeout for listening method]\n\nSIZE\n[-p/--payload-size ICMP payload size] OR [-d/--datagram-size size of whole packet]\n[-r/--random-size-avgstd set random, normally distributed packet sizes - enter average and standard deviation]\n\nOUTPUT\n[-c/--csv output reply information to a csv file]\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + else + { + + /* Check if we're root. If not, we can't create the raw socket necessary for ICMP */ + if(getuid()!=0 && geteuid()!=0) + { + printf("UID: %d EUID: %d", getuid(), geteuid()); + printf("\nCan't run. I need root permissions to create raw socket. Sorry.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + + /* Create socket descriptor for sending and receiving traffic */ + socketDescriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + + /* Drop root permissions */ + seteuid(501); + setuid(getuid()); + + } + for(int i = 2; i < argc; i++) { + // argv[0] is the ./a which is input + // argv[1] is the address (IPv4, DNS, IPv6) + if(strcmp(argv[i],"-q") == 0 || strcmp(argv[i],"--request-time") == 0) + { + if(timeBetweenRepReq || randTimeMinMax || randTimeAvgStd) + { + printf("-q flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + timeBetweenReq = true; + msecsBetweenReq = atoi(argv[i + 1]); + printf("Flag -q set! Waiting %f milliseconds between ping requests.\n", msecsBetweenReq); + i++; + } + else + { + printf("-q flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--reply-request-time") == 0) + { + if(timeBetweenReq || randTimeMinMax || randTimeAvgStd) + { + printf("-b flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + timeBetweenRepReq = true; + msecsBetweenRepReq = atoi(argv[i + 1]); + printf("Flag -b set! Waiting %d milliseconds between receiving a reply and sending a request\n", msecsBetweenRepReq); + i++; + } + else + { + printf("-b flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--datagram-size") == 0) + { + if(payloadSize || randSizeMinMax || randSizeAvgStd) + { + printf("-d flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + datagramSizeSet = true; + icmpPayloadLength = atoi(argv[i + 1]) - ICMP_MINLEN - IP_MINLENGTH; + if(icmpPayloadLength < 8) + { + printf("Error: datagram size must be greater than 50 bytes.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + printf("Flag -d set! Datagram will be %d bytes large.\n", icmpPayloadLength+IP_MINLENGTH+ICMP_MINLEN); + i++; + } + else + { + printf("-d flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--payload-size") == 0) + { + if(datagramSizeSet || randSizeMinMax || randSizeAvgStd) + { + printf("-p flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + payloadSize = true; + icmpPayloadLength = atoi(argv[i + 1]); + if(icmpPayloadLength < 8) + { + printf("Error: Payload size must be 8 bytes or greater.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + printf("Flag -p set! Payload size will be %d bytes large.\n", icmpPayloadLength); + i++; + } + else + { + printf("-p flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--random-size-minmax") == 0) + { + if(datagramSizeSet || payloadSize || increasingSize || randSizeAvgStd) + { + printf("-l flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randSizeMinMax = true; + if(atoi(argv[i + 1]) > atoi(argv[i + 2])) + { + bytesSizeMin = atoi(argv[i + 2]); + bytesSizeMax = atoi(argv[i + 1]); + } + else + { + bytesSizeMin = atoi(argv[i + 1]); + bytesSizeMax = atoi(argv[i + 2]); + } + printf("Flag -l set! Random size will be between %d ", bytesSizeMin); + printf("and %d.\n", bytesSizeMax); + i += 2; + } + else + { + printf("-l flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-r") == 0 || strcmp(argv[i],"--random-size-avgstd") == 0) + { + if(datagramSizeSet || payloadSize || increasingSize || randSizeMinMax) + { + printf("-r flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randSizeAvgStd = true; + bytesSizeAvg = atoi(argv[i + 1]); + bytesSizeStd = atoi(argv[i + 2]); + printf("Flag -r set! Random size will average %d",bytesSizeAvg); + printf(" with a std. dev. of %d.\n", bytesSizeStd); + i += 2; + } + else + { + printf("-r flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--random-time-minmax") == 0) + { + if(timeBetweenReq || timeBetweenRepReq || randTimeAvgStd) + { + printf("-s flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randTimeMinMax = true; + if(atoi(argv[i + 1]) > atoi(argv[i + 2])) + { + msecsTimeMin = atoi(argv[i + 2]); + msecsTimeMax = atoi(argv[i + 1]); + } + else + { + msecsTimeMin = atoi(argv[i + 1]); + msecsTimeMax = atoi(argv[i + 2]); + } + printf("Flag -s set! Random time between requests will be between %d ", msecsTimeMin); + printf("and %d.\n", msecsTimeMax); + i += 2; + } + else + { + printf("-s flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-t") == 0 || strcmp(argv[i],"--random-time-avgstd") == 0) + { + if(timeBetweenReq || timeBetweenRepReq || randTimeMinMax) + { + printf("-t flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randTimeAvgStd = true; + msecsTimeAvg = atoi(argv[i + 1]); + msecsTimeStd = atoi(argv[i + 2]); + printf("Flag -t set! Random time between requests will average %d ",msecsTimeAvg); + printf("with a std. dev. of %d.\n", msecsTimeStd); + i += 2; + } + else + { + printf("-t flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--increasing-size") == 0) + { + if(datagramSizeSet || payloadSize || randSizeMinMax || randSizeAvgStd) + { + printf("-i flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + increasingSize = true; + sizeInitial = atoi(argv[i + 1]); + sizeGrowth = atoi(argv[i + 2]); + if(sizeInitial >= (IP_MINLENGTH + ICMP_MINLENGTH)) + { + printf("Flag -i set! Pings will have an initial size of %d ", sizeInitial); + printf("and grow at a rate of %d per request.\n", sizeGrowth); + + //Subtract growth from initial once so when we ping, we can add sizeGrowth to it every time, + //and initialGrowth is still proper + icmpPayloadLength = sizeInitial - sizeGrowth - IP_MINLENGTH - ICMP_MINLENGTH + 8; + } + else + { + printf("Problem: Initial size must be greater than IP header size plus the ICMP header size (%d).\n", IP_MINLENGTH + ICMP_MINLENGTH); + return(1); + } + i += 2; + } + else + { + printf("-i flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-e") == 0 || strcmp(argv[i],"--exclude") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + excludingPing = true; + pingsToExclude = atoi(argv[i + 1]); + if(pingsToExclude >= pingsToSend) + { + printf("Trying to exclude more pings than you send huh? Not funny.\n"); + exit(0); + } + printf("Flag -e set! %d earliest pings to be excluded from final statistics.\n", pingsToExclude); + i++; + } + else + { + printf("-e flag not set, requires parameter.\n"); + } + + } + else if(strcmp(argv[i],"-n") == 0 || strcmp(argv[i],"--pings-to-send") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + multiplePings = true; + pingsToSend = atoi(argv[i + 1]); + printf("Flag -n set! %d pings to be sent.\n", pingsToSend); + i++; + } + else + { + printf("-n flag not set, requires parameter.\n"); + + } + + } + else if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--csv") == 0) + { + csvMode = 1; + if(i + 1 < argc) + { + csvFileName = argv[i+1]; + i++; + } + else + { + csvFileName = "output.csv"; + } + /* Open the CSV file */ + csvOutput.open(csvFileName); + printf("Flag -c set! Replies will be output to %s.\n", csvFileName.c_str()); + } + else if(strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--timeout") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + timeoutInput = atoi(argv[i + 1]); + i++; + } + + printf("Flag -z set! Listening timeout will be set to %d seconds.\n", timeoutInput); + } + else + { + printf("Flag not recognized, \"%s\"\n",argv[i]); + } + } + printf("Destination set to: %s\n", argv[1]); + + struct addrinfo *result, hints; + hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_RAW; /* RAW socket */ + hints.ai_flags = AI_PASSIVE; /* Fill in my IP address */ + int status; + + /* Convert address */ + if((status = getaddrinfo(destination, NULL, &hints, &result)) != 0) + { + printf("getaddrinfo error: %s\n", gai_strerror(status)); + printf("Double check the address that you want to ping.\n"); + exit(1); + } + + whereto = (struct sockaddr_in *)result->ai_addr; + + + /* + + WINDOWS block for setting the source and destination IP address + + */ + #if WIN32 + sockAddress = &whereto; + int sizeOfAddress=sizeof(IPHeader.destinationIPAddress); + if(WSAStringToAddress((char *)destination,AF_INET,NULL,(LPSOCKADDR)&IPHeader.destinationIPAddress.S_un.S_un_W,&sizeOfAddress)!=0) + { + int error=WSAGetLastError(); + std::cout<sin_addr),(int*)sizeof(socketAddress->sin_addr))!=0) + { + int error=WSAGetLastError(); + std::cout< distribution(bytesSizeAvg, bytesSizeStd); + std::normal_distribution distribution2(msecsTimeAvg, msecsTimeStd); + + + /* Specify that we want two threads (one for listening, one for sending) */ + omp_set_num_threads(2); + + /* + + Execute the ping/listen functions in sequential mode (wait for reply before sending request) + + */ + if(timeBetweenRepReq) + { + while(pingsSent < pingsToSend) + { + + pingICMP(socketDescriptor, icmpPayloadLength); + listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); + usleep(msecsBetweenRepReq * 1000); + } + + } + + /* + + Execute the ping/listen functions in parallel with OpenMP threading + + */ + else + { + + #pragma omp parallel sections + { + + /* Sending block */ + #pragma omp section + for (i = 0; i < pingsToSend; i++) + { + /* Ping */ + if(randSizeAvgStd) + { + randomDatagramSize = distribution(generator); + pingICMP(socketDescriptor, randomDatagramSize - IP_MINLENGTH - ICMP_MINLEN); + } + else if(increasingSize) + { + icmpPayloadLength += sizeGrowth; + pingICMP(socketDescriptor, icmpPayloadLength); + } + else + { + pingICMP(socketDescriptor, icmpPayloadLength); + } + + /* Wait */ + if(randTimeAvgStd) + { + randomTime = distribution2(generator); + usleep(randomTime * 1000); + } + else + { + usleep(msecsBetweenReq * 1000); + } + } + + /* Listening block */ + #pragma omp section + while(i != pingsToSend - 1 && pingsToSend != pingsReceived + packetsTimedOut && killSwitch) + { + + /* If we're excluding some pings, listen but don't print any info */ + if(excludingPing && pingsReceived < pingsToExclude) + { + listenICMP(socketDescriptor, &sourceSocket, 1, 1, timeoutInput); + } + + /* If we're outputting to a CSV file, don't print out so much on the terminal */ + else if(csvMode) + { + listenICMP(socketDescriptor, &sourceSocket, 1, 0, timeoutInput); + } + + /* Otherwise, print all statistics and information to the terminal */ + else + { + listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); + } + + } + + } + } + + /* Print final statistics and quit */ + report(); + + if(csvMode) + { + csvOutput.close(); + } + #ifdef WIN32 + int result = WSACleanup(); + #endif + return(0); + } + + void interrupt(int signal) + { + if(killSwitch) + { + pingsToSend = 0; + killSwitch = false; + } + } From 086463d82f0591973f289ff26d8c2181aca5d581 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 26 Jan 2015 17:26:36 -0600 Subject: [PATCH 3/7] added a custom painted picture to res folder --- res/picture.png | Bin 0 -> 18065 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 res/picture.png diff --git a/res/picture.png b/res/picture.png new file mode 100644 index 0000000000000000000000000000000000000000..0524a970628c02b90fd22dd6a7b0d83c0bb37d31 GIT binary patch literal 18065 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 Date: Mon, 2 Feb 2015 16:24:31 -0600 Subject: [PATCH 4/7] moved custom folder into /res --- {moralesty1 => res/moralesty1}/.DS_Store | Bin {moralesty1 => res/moralesty1}/ping.c | 0 {moralesty1 => res/moralesty1}/pong.cpp | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename {moralesty1 => res/moralesty1}/.DS_Store (100%) rename {moralesty1 => res/moralesty1}/ping.c (100%) rename {moralesty1 => res/moralesty1}/pong.cpp (100%) diff --git a/moralesty1/.DS_Store b/res/moralesty1/.DS_Store similarity index 100% rename from moralesty1/.DS_Store rename to res/moralesty1/.DS_Store diff --git a/moralesty1/ping.c b/res/moralesty1/ping.c similarity index 100% rename from moralesty1/ping.c rename to res/moralesty1/ping.c diff --git a/moralesty1/pong.cpp b/res/moralesty1/pong.cpp similarity index 100% rename from moralesty1/pong.cpp rename to res/moralesty1/pong.cpp From 34ceb3bd4f2c0a13c3f1f2c227d35827a5a81578 Mon Sep 17 00:00:00 2001 From: moralesty1 Date: Tue, 12 May 2015 10:21:26 -0500 Subject: [PATCH 5/7] Fixing assignment on --- src/moralesty1/ping.c | 1191 +++++++++++++++++++++++++++++++++++++++ src/moralesty1/pong.cpp | 989 ++++++++++++++++++++++++++++++++ 2 files changed, 2180 insertions(+) create mode 100644 src/moralesty1/ping.c create mode 100644 src/moralesty1/pong.cpp diff --git a/src/moralesty1/ping.c b/src/moralesty1/ping.c new file mode 100644 index 0000000..4c4b95e --- /dev/null +++ b/src/moralesty1/ping.c @@ -0,0 +1,1191 @@ +/* +* Copyright (c) 1989 The Regents of the University of California. +* All rights reserved. +* +* This code is derived from software contributed to Berkeley by +* Mike Muuss. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* 1. Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* 2. Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* 3. All advertising materials mentioning features or use of this software +* must display the following acknowledgement: +* This product includes software developed by the University of +* California, Berkeley and its contributors. +* 4. Neither the name of the University nor the names of its contributors +* may be used to endorse or promote products derived from this software +* without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n" +"All rights reserved.\n"; +/* +* From: @(#)ping.c 5.9 (Berkeley) 5/12/91 +*/ +char rcsid[] = "$Id: ping.c,v 1.22 1997/06/08 19:39:47 dholland Exp $"; +char pkg[] = "netkit-base-0.10"; + +/* +* P I N G . C +* +* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, +* measure round-trip-delays and packet loss across network paths. +* +* Author - +* Mike Muuss +* U. S. Army Ballistic Research Laboratory +* December, 1983 +* +* Status - +* Public Domain. Distribution Unlimited. +* Bugs - +* More statistics could always be gathered. +* This program has to run SUID to ROOT to access the ICMP socket. +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +* Note: on some systems dropping root makes the process dumpable or +* traceable. In that case if you enable dropping root and someone +* traces ping, they get control of a raw socket and can start +* spoofing whatever packets they like. SO BE CAREFUL. +*/ +#ifdef __linux__ +#define SAFE_TO_DROP_ROOT +#endif + +#if defined(__GLIBC__) && (__GLIBC__ >= 2) +#define icmphdr icmp +#define ICMP_DEST_UNREACH ICMP_UNREACH +#define ICMP_NET_UNREACH ICMP_UNREACH_NET +#define ICMP_HOST_UNREACH ICMP_UNREACH_HOST +#define ICMP_PORT_UNREACH ICMP_UNREACH_PORT +#define ICMP_PROT_UNREACH ICMP_UNREACH_PROTOCOL +#define ICMP_FRAG_NEEDED ICMP_UNREACH_NEEDFRAG +#define ICMP_SR_FAILED ICMP_UNREACH_SRCFAIL +#define ICMP_NET_UNKNOWN ICMP_UNREACH_NET_UNKNOWN +#define ICMP_HOST_UNKNOWN ICMP_UNREACH_HOST_UNKNOWN +#define ICMP_HOST_ISOLATED ICMP_UNREACH_ISOLATED +#define ICMP_NET_UNR_TOS ICMP_UNREACH_TOSNET +#define ICMP_HOST_UNR_TOS ICMP_UNREACH_TOSHOST +#define ICMP_SOURCE_QUENCH ICMP_SOURCEQUENCH +#define ICMP_REDIR_NET ICMP_REDIRECT_NET +#define ICMP_REDIR_HOST ICMP_REDIRECT_HOST +#define ICMP_REDIR_NETTOS ICMP_REDIRECT_TOSNET +#define ICMP_REDIR_HOSTTOS ICMP_REDIRECT_TOSHOST +#define ICMP_TIME_EXCEEDED ICMP_TIMXCEED +#define ICMP_EXC_TTL ICMP_TIMXCEED_INTRANS +#define ICMP_EXC_FRAGTIME ICMP_TIMXCEED_REASS +#define ICMP_PARAMETERPROB ICMP_PARAMPROB +#define ICMP_TIMESTAMP ICMP_TSTAMP +#define ICMP_TIMESTAMPREPLY ICMP_TSTAMPREPLY +#define ICMP_INFO_REQUEST ICMP_IREQ +#define ICMP_INFO_REPLY ICMP_IREQREPLY +#else +#define ICMP_MINLEN 28 +#define inet_ntoa(x) inet_ntoa(*((struct in_addr *)&(x))) +#endif + + +#define DEFDATALEN (64 - 8) /* default data length */ +#define MAXIPLEN 60 +#define MAXICMPLEN 76 +#define MAXPACKET (65536 - 60 - 8)/* max packet size */ +#define MAXWAIT 10 /* max seconds to wait for response */ +#define NROUTES 9 /* number of record route slots */ + +#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)) + +/* various options */ +int options; +#define F_FLOOD 0x001 +#define F_INTERVAL 0x002 +#define F_NUMERIC 0x004 +#define F_PINGFILLED 0x008 +#define F_QUIET 0x010 +#define F_RROUTE 0x020 +#define F_SO_DEBUG 0x040 +#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 +* to 8192 for complete accuracy... +*/ +#define MAX_DUP_CHK (8 * 128) +int mx_dup_ck = MAX_DUP_CHK; +char rcvd_tbl[MAX_DUP_CHK / 8]; + +struct sockaddr whereto; /* who to ping */ +int datalen = DEFDATALEN; +int s; /* socket file descriptor */ +u_char outpack[MAXPACKET]; +char BSPACE = '\b'; /* characters written for flood */ +char DOT = '.'; +static char *hostname; +static int ident; /* process id to identify our packets */ + +/* counters */ +static long npackets; /* max packets to transmit */ +static long nreceived; /* # of packets we got back */ +static long nrepeats; /* number of duplicates */ +static long ntransmitted; /* sequence # for outbound packets = #sent */ +static int interval = 1; /* interval between packets */ + +/* timing */ +static int timing; /* flag to do timing */ +static long tmin = LONG_MAX; /* minimum round trip time */ +static long tmax = 0; /* maximum round trip time */ +static u_long tsum; /* sum of all times, for doing average */ + +/* protos */ +static char *pr_addr(u_long); +static int in_cksum(u_short *addr, int len); +static void catcher(int); +static void finish(int ignore); +static void pinger(void); +static void fill(void *bp, char *patp); +static void usage(void); +static void pr_pack(char *buf, int cc, struct sockaddr_in *from); +static void tvsub(struct timeval *out, struct timeval *in); +static void pr_icmph(struct icmphdr *icp); +static void pr_retip(struct iphdr *ip); + + +int +main(int argc, char *argv[]) +{ + struct timeval timeout; + struct hostent *hp; + struct sockaddr_in *to; + struct protoent *proto; + struct in_addr ifaddr; + int i; + int ch, fdmask, hold, packlen, preload; + u_char *datap, *packet; + char *target, hnamebuf[MAXHOSTNAMELEN]; + u_char ttl, loop; + int am_i_root; + #ifdef IP_OPTIONS + char rspace[3 + 4 * NROUTES + 1]; /* record route space */ + #endif + + static char *null = NULL; + __environ = &null; + am_i_root = (getuid()==0); + + /* + * Pull this stuff up front so we can drop root if desired. + */ + if (!(proto = getprotobyname("icmp"))) { + (void)fprintf(stderr, "ping: unknown protocol icmp.\n"); + exit(2); + } + if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { + if (errno==EPERM) { + fprintf(stderr, "ping: ping must run as root\n"); + } + else perror("ping: socket"); + exit(2); + } + + #ifdef SAFE_TO_DROP_ROOT + setuid(getuid()); + #endif + + preload = 0; + datap = &outpack[8 + sizeof(struct timeval)]; + while ((ch = getopt(argc, argv, "I:LRc:dfh:i:l:np:qrs:t:v")) != EOF) + switch(ch) { + case 'c': + npackets = atoi(optarg); + if (npackets <= 0) { + (void)fprintf(stderr, + "ping: bad number of packets to transmit.\n"); + exit(2); + } + break; + case 'd': + options |= F_SO_DEBUG; + break; + case 'f': + if (!am_i_root) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(2); + } + options |= F_FLOOD; + setbuf(stdout, NULL); + break; + case 'i': /* wait between sending packets */ + interval = atoi(optarg); + if (interval <= 0) { + (void)fprintf(stderr, + "ping: bad timing interval.\n"); + exit(2); + } + options |= F_INTERVAL; + break; + case 'l': + if (!am_i_root) { + (void)fprintf(stderr, + "ping: %s\n", strerror(EPERM)); + exit(2); + } + preload = atoi(optarg); + if (preload < 0) { + (void)fprintf(stderr, + "ping: bad preload value.\n"); + exit(2); + } + break; + case 'n': + options |= F_NUMERIC; + break; + case 'p': /* fill buffer with user pattern */ + options |= F_PINGFILLED; + fill(datap, optarg); + break; + case 'q': + options |= F_QUIET; + break; + case 'R': + options |= F_RROUTE; + break; + case 'r': + options |= F_SO_DONTROUTE; + break; + case 's': /* size of packet to send */ + datalen = atoi(optarg); + if (datalen > MAXPACKET) { + (void)fprintf(stderr, + "ping: packet size too large.\n"); + exit(2); + } + if (datalen <= 0) { + (void)fprintf(stderr, + "ping: illegal packet size.\n"); + exit(2); + } + break; + 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(2); + } + ttl = i; + break; + case 'I': + moptions |= MULTICAST_IF; + { + int i1, i2, i3, i4; + char junk; + + if (sscanf(optarg, "%u.%u.%u.%u%c", + &i1, &i2, &i3, &i4, &junk) != 4) { + printf("bad interface address '%s'\n", + optarg); + exit(2); + } + 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; + + memset(&whereto, 0, sizeof(struct sockaddr)); + to = (struct sockaddr_in *)&whereto; + to->sin_family = AF_INET; + if (inet_aton(target, &to->sin_addr)) { + hostname = target; + } + else { + hp = gethostbyname(target); + if (!hp) { + (void)fprintf(stderr, + "ping: unknown host %s\n", target); + exit(2); + } + to->sin_family = hp->h_addrtype; + if (hp->h_length > (int)sizeof(to->sin_addr)) { + hp->h_length = sizeof(to->sin_addr); + } + memcpy(&to->sin_addr, hp->h_addr, hp->h_length); + (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); + hostname = hnamebuf; + } + + if (options & F_FLOOD && options & F_INTERVAL) { + (void)fprintf(stderr, + "ping: -f and -i incompatible options.\n"); + exit(2); + } + + if (datalen >= (int)sizeof(struct timeval)) /* can we time transfer */ + timing = 1; + packlen = datalen + MAXIPLEN + MAXICMPLEN; + packet = malloc((u_int)packlen); + if (!packet) { + (void)fprintf(stderr, "ping: out of memory.\n"); + exit(2); + } + if (!(options & F_PINGFILLED)) + for (i = 8; i < datalen; ++i) + *datap++ = i; + + ident = getpid() & 0xFFFF; + hold = 1; + + if (options & F_SO_DEBUG) + (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, + sizeof(hold)); + + if (options & F_SO_DONTROUTE) + (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, + sizeof(hold)); + + /* this is necessary for broadcast pings to work */ + setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&hold, sizeof(hold)); + + /* record route option */ + if (options & F_RROUTE) { + #ifdef IP_OPTIONS + memset(rspace, 0, sizeof(rspace)); + rspace[IPOPT_OPTVAL] = IPOPT_RR; + rspace[IPOPT_OLEN] = sizeof(rspace)-1; + rspace[IPOPT_OFFSET] = IPOPT_MINOFF; + if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, + sizeof(rspace)) < 0) { + perror("ping: record route"); + exit(2); + } + #else + (void)fprintf(stderr, + "ping: record route not available in this implementation.\n"); + exit(2); + #endif /* IP_OPTIONS */ + } + + /* + * When pinging the broadcast address, you can get a lot of answers. + * Doing something so evil is useful if you are trying to stress the + * ethernet, or just want to fill the arp cache to get some stuff for + * /etc/ethers. + */ + hold = 48 * 1024; + (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, + sizeof(hold)); + + /*#if 0*/ + 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); + } + } + /*#endif*/ + + 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), + datalen); + else + (void)printf("PING %s: %d data bytes\n", hostname, datalen); + + (void)signal(SIGINT, finish); + (void)signal(SIGALRM, catcher); + + while (preload--) /* fire off them quickies */ + pinger(); + + if ((options & F_FLOOD) == 0) + catcher(0); /* start things going */ + + for (;;) { + struct sockaddr_in from; + register int cc; + size_t fromlen; + + if (options & F_FLOOD) { + pinger(); + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + fdmask = 1 << s; + if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL, + (fd_set *)NULL, &timeout) < 1) + continue; + } + fromlen = sizeof(from); + if ((cc = recvfrom(s, (char *)packet, packlen, 0, + (struct sockaddr *)&from, &fromlen)) < 0) { + if (errno == EINTR) + continue; + perror("ping: recvfrom"); + continue; + } + pr_pack((char *)packet, cc, &from); + if (npackets && nreceived >= npackets) + break; + } + finish(0); + /* NOTREACHED */ + return 0; + } + + /* + * catcher -- + * This routine causes another PING to be transmitted, and then + * schedules another SIGALRM for 1 second from now. + * + * bug -- + * Our sense of time will slowly skew (i.e., packets will not be + * launched exactly at 1-second intervals). This does not affect the + * quality of the delay and loss statistics. + */ + static void + catcher(int ignore) + { + int waittime; + + (void)ignore; + pinger(); + (void)signal(SIGALRM, catcher); + if (!npackets || ntransmitted < npackets) + alarm((u_int)interval); + else { + if (nreceived) { + waittime = 2 * tmax / 1000; + if (!waittime) + waittime = 1; + if (waittime > MAXWAIT) + waittime = MAXWAIT; + } else + waittime = MAXWAIT; + (void)signal(SIGALRM, finish); + (void)alarm((u_int)waittime); + } + } + + #if !defined(__GLIBC__) || (__GLIBC__ < 2) + #define icmp_type type + #define icmp_code code + #define icmp_cksum checksum + #define icmp_id un.echo.id + #define icmp_seq un.echo.sequence + #define icmp_gwaddr un.gateway + #endif /* __GLIBC__ */ + + #define ip_hl ihl + #define ip_v version + #define ip_tos tos + #define ip_len tot_len + #define ip_id id + #define ip_off frag_off + #define ip_ttl ttl + #define ip_p protocol + #define ip_sum check + #define ip_src saddr + #define ip_dst daddr + + /* + * pinger -- + * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet + * will be added on by the kernel. The ID field is our UNIX process ID, + * and the sequence number is an ascending integer. The first 8 bytes + * of the data portion are used to hold a UNIX "timeval" struct in VAX + * byte-order, to compute the round-trip time. + */ + static void + pinger(void) + { + register struct icmphdr *icp; + register int cc; + int i; + + icp = (struct icmphdr *)outpack; + icp->icmp_type = ICMP_ECHO; + icp->icmp_code = 0; + icp->icmp_cksum = 0; + icp->icmp_seq = ntransmitted++; + icp->icmp_id = ident; /* ID */ + + CLR(icp->icmp_seq % mx_dup_ck); + + if (timing) + (void)gettimeofday((struct timeval *)&outpack[8], + (struct timezone *)NULL); + + cc = datalen + 8; /* skips ICMP portion */ + + /* compute ICMP checksum here */ + icp->icmp_cksum = in_cksum((u_short *)icp, cc); + + i = sendto(s, (char *)outpack, cc, 0, &whereto, + sizeof(struct sockaddr)); + + if (i < 0 || i != cc) { + if (i < 0) + perror("ping: sendto"); + (void)printf("ping: wrote %s %d chars, ret=%d\n", + hostname, cc, i); + } + if (!(options & F_QUIET) && options & F_FLOOD) + (void)write(STDOUT_FILENO, &DOT, 1); + } + + /* + * pr_pack -- + * Print out the packet, if it came from us. This logic is necessary + * because ALL readers of the ICMP socket get a copy of ALL ICMP packets + * which arrive ('tis only fair). This permits multiple copies of this + * program to be run without having intermingled output (or statistics!). + */ + void + pr_pack(char *buf, int cc, struct sockaddr_in *from) + { + register struct icmphdr *icp; + register int i; + register u_char *cp,*dp; + /*#if 0*/ + register u_long l; + register int j; + static int old_rrlen; + static char old_rr[MAX_IPOPTLEN]; + /*#endif*/ + struct iphdr *ip; + struct timeval tv, *tp; + long triptime = 0; + int hlen, dupflag; + + (void)gettimeofday(&tv, (struct timezone *)NULL); + + /* Check the IP header */ + ip = (struct iphdr *)buf; + hlen = ip->ip_hl << 2; + if (cc < datalen + ICMP_MINLEN) { + if (options & F_VERBOSE) + (void)fprintf(stderr, + "ping: packet too short (%d bytes) from %s\n", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr)); + return; + } + + /* Now the ICMP part */ + cc -= hlen; + icp = (struct icmphdr *)(buf + hlen); + if (icp->icmp_type == ICMP_ECHOREPLY) { + if (icp->icmp_id != ident) + return; /* 'Twas not our ECHO */ + ++nreceived; + if (timing) { + #ifndef icmp_data + tp = (struct timeval *)(icp + 1); + #else + tp = (struct timeval *)icp->icmp_data; + #endif + tvsub(&tv, tp); + triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); + tsum += triptime; + if (triptime < tmin) + tmin = triptime; + if (triptime > tmax) + tmax = triptime; + } + + if (TST(icp->icmp_seq % mx_dup_ck)) { + ++nrepeats; + --nreceived; + dupflag = 1; + } else { + SET(icp->icmp_seq % mx_dup_ck); + dupflag = 0; + } + + if (options & F_QUIET) + return; + + if (options & F_FLOOD) + (void)write(STDOUT_FILENO, &BSPACE, 1); + else { + (void)printf("%d bytes from %s: icmp_seq=%u", cc, + inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), + icp->icmp_seq); + (void)printf(" ttl=%d", ip->ip_ttl); + if (timing) + (void)printf(" time=%ld.%ld ms", triptime/10, + triptime%10); + if (dupflag) + (void)printf(" (DUP!)"); + /* check the data */ + #ifndef icmp_data + cp = ((u_char*)(icp + 1) + 8); + #else + cp = (u_char*)icp->icmp_data + 8; + #endif + dp = &outpack[8 + sizeof(struct timeval)]; + for (i = 8; i < datalen; ++i, ++cp, ++dp) { + if (*cp != *dp) { + (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", + i, *dp, *cp); + cp = (u_char*)(icp + 1); + for (i = 8; i < datalen; ++i, ++cp) { + if ((i % 32) == 8) + (void)printf("\n\t"); + (void)printf("%x ", *cp); + } + break; + } + } + } + } else { + /* We've got something other than an ECHOREPLY */ + if (!(options & F_VERBOSE)) + return; + (void)printf("%d bytes from %s: ", cc, + pr_addr(from->sin_addr.s_addr)); + pr_icmph(icp); + } + + /*#if 0*/ + /* Display any IP options */ + cp = (u_char *)buf + sizeof(struct iphdr); + + for (; hlen > (int)sizeof(struct iphdr); --hlen, ++cp) + switch (*cp) { + case IPOPT_EOL: + hlen = 0; + break; + case IPOPT_LSRR: + (void)printf("\nLSRR: "); + hlen -= 2; + j = *++cp; + ++cp; + if (j > IPOPT_MINOFF) + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + j -= 4; + if (j <= IPOPT_MINOFF) + break; + (void)putchar('\n'); + } + break; + case IPOPT_RR: + j = *++cp; /* get length */ + i = *++cp; /* and pointer */ + hlen -= 2; + if (i > j) + i = j; + i -= IPOPT_MINOFF; + if (i <= 0) + continue; + if (i == old_rrlen + && cp == (u_char *)buf + sizeof(struct iphdr) + 2 + && !memcmp((char *)cp, old_rr, i) + && !(options & F_FLOOD)) { + (void)printf("\t(same route)"); + i = ((i + 3) / 4) * 4; + hlen -= i; + cp += i; + break; + } + old_rrlen = i; + memcpy(old_rr, cp, i); + (void)printf("\nRR: "); + for (;;) { + l = *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + l = (l<<8) + *++cp; + if (l == 0) + (void)printf("\t0.0.0.0"); + else + (void)printf("\t%s", pr_addr(ntohl(l))); + hlen -= 4; + i -= 4; + if (i <= 0) + break; + (void)putchar('\n'); + } + break; + case IPOPT_NOP: + (void)printf("\nNOP"); + break; + default: + (void)printf("\nunknown option %x", *cp); + break; + } + /*#endif*/ + if (!(options & F_FLOOD)) { + (void)putchar('\n'); + (void)fflush(stdout); + } + } + + /* + * in_cksum -- + * Checksum routine for Internet Protocol family headers (C Version) + */ + static int + in_cksum(u_short *addr, int len) + { + register int nleft = len; + register u_short *w = addr; + register int sum = 0; + u_short answer = 0; + + /* + * Our algorithm is simple, using a 32 bit accumulator (sum), we add + * sequential 16 bit words to it, and at the end, fold back all the + * carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) { + sum += *w++; + nleft -= 2; + } + + /* mop up an odd byte, if necessary */ + if (nleft == 1) { + *(u_char *)(&answer) = *(u_char *)w ; + sum += answer; + } + + /* add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = ~sum; /* truncate to 16 bits */ + return(answer); + } + + /* + * tvsub -- + * Subtract 2 timeval structs: out = out - in. Out is assumed to + * be >= in. + */ + static void + tvsub(register struct timeval *out, register struct timeval *in) + { + if ((out->tv_usec -= in->tv_usec) < 0) { + --out->tv_sec; + out->tv_usec += 1000000; + } + out->tv_sec -= in->tv_sec; + } + + /* + * finish -- + * Print out statistics, and give up. + */ + static void + finish(int ignore) + { + (void)ignore; + + (void)signal(SIGINT, SIG_IGN); + (void)putchar('\n'); + (void)fflush(stdout); + (void)printf("--- %s ping statistics ---\n", hostname); + (void)printf("%ld packets transmitted, ", ntransmitted); + (void)printf("%ld packets received, ", nreceived); + if (nrepeats) + (void)printf("+%ld duplicates, ", nrepeats); + if (ntransmitted) + if (nreceived > ntransmitted) + (void)printf("-- somebody's printing up packets!"); + else + (void)printf("%d%% packet loss", + (int) (((ntransmitted - nreceived) * 100) / + ntransmitted)); + (void)putchar('\n'); + if (nreceived && timing) + (void)printf("round-trip min/avg/max = %ld.%ld/%lu.%ld/%ld.%ld ms\n", + tmin/10, tmin%10, + (tsum / (nreceived + nrepeats))/10, + (tsum / (nreceived + nrepeats))%10, + tmax/10, tmax%10); + + if (nreceived==0) exit(1); + exit(0); + } + + #ifdef notdef + static char *ttab[] = { + "Echo Reply", /* ip + seq + udata */ + "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ + "Source Quench", /* IP */ + "Redirect", /* redirect type, gateway, + IP */ + "Echo", + "Time Exceeded", /* transit, frag reassem + IP */ + "Parameter Problem", /* pointer + IP */ + "Timestamp", /* id + seq + three timestamps */ + "Timestamp Reply", /* " */ + "Info Request", /* id + sq */ + "Info Reply" /* " */ + }; + #endif + + /* + * pr_icmph -- + * Print a descriptive string about an ICMP header. + */ + static void + pr_icmph(struct icmphdr *icp) + { + switch(icp->icmp_type) { + case ICMP_ECHOREPLY: + (void)printf("Echo Reply\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_DEST_UNREACH: + switch(icp->icmp_code) { + case ICMP_NET_UNREACH: + (void)printf("Destination Net Unreachable\n"); + break; + case ICMP_HOST_UNREACH: + (void)printf("Destination Host Unreachable\n"); + break; + case ICMP_PROT_UNREACH: + (void)printf("Destination Protocol Unreachable\n"); + break; + case ICMP_PORT_UNREACH: + (void)printf("Destination Port Unreachable\n"); + break; + case ICMP_FRAG_NEEDED: + (void)printf("frag needed and DF set\n"); + break; + case ICMP_SR_FAILED: + (void)printf("Source Route Failed\n"); + break; + case ICMP_NET_UNKNOWN: + (void)printf("Network Unknown\n"); + break; + case ICMP_HOST_UNKNOWN: + (void)printf("Host Unknown\n"); + break; + case ICMP_HOST_ISOLATED: + (void)printf("Host Isolated\n"); + break; + case ICMP_NET_UNR_TOS: + printf("Destination Network Unreachable At This TOS\n"); + break; + case ICMP_HOST_UNR_TOS: + printf("Destination Host Unreachable At This TOS\n"); + break; + #ifdef ICMP_PKT_FILTERED + case ICMP_PKT_FILTERED: + (void)printf("Packet Filtered\n"); + break; + #endif + #ifdef ICMP_PREC_VIOLATION + case ICMP_PREC_VIOLATION: + (void)printf("Precedence Violation\n"); + break; + #endif + #ifdef ICMP_PREC_CUTOFF + case ICMP_PREC_CUTOFF: + (void)printf("Precedence Cutoff\n"); + break; + #endif + default: + (void)printf("Dest Unreachable, Unknown Code: %d\n", + icp->icmp_code); + break; + } + /* Print returned IP header information */ + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_SOURCE_QUENCH: + (void)printf("Source Quench\n"); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_REDIRECT: + switch(icp->icmp_code) { + case ICMP_REDIR_NET: + (void)printf("Redirect Network"); + break; + case ICMP_REDIR_HOST: + (void)printf("Redirect Host"); + break; + case ICMP_REDIR_NETTOS: + (void)printf("Redirect Type of Service and Network"); + break; + case ICMP_REDIR_HOSTTOS: + (void)printf("Redirect Type of Service and Host"); + break; + default: + (void)printf("Redirect, Bad Code: %d", icp->icmp_code); + break; + } + (void)printf("(New addr: %s)\n", + inet_ntoa(icp->icmp_gwaddr)); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_ECHO: + (void)printf("Echo Request\n"); + /* XXX ID + Seq + Data */ + break; + case ICMP_TIME_EXCEEDED: + switch(icp->icmp_code) { + case ICMP_EXC_TTL: + (void)printf("Time to live exceeded\n"); + break; + case ICMP_EXC_FRAGTIME: + (void)printf("Frag reassembly time exceeded\n"); + break; + default: + (void)printf("Time exceeded, Bad Code: %d\n", + icp->icmp_code); + break; + } + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_PARAMETERPROB: + (void)printf("Parameter problem: IP address = %s\n", + inet_ntoa (icp->icmp_gwaddr)); + #ifndef icmp_data + pr_retip((struct iphdr *)(icp + 1)); + #else + pr_retip((struct iphdr *)icp->icmp_data); + #endif + break; + case ICMP_TIMESTAMP: + (void)printf("Timestamp\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_TIMESTAMPREPLY: + (void)printf("Timestamp Reply\n"); + /* XXX ID + Seq + 3 timestamps */ + break; + case ICMP_INFO_REQUEST: + (void)printf("Information Request\n"); + /* XXX ID + Seq */ + break; + case ICMP_INFO_REPLY: + (void)printf("Information Reply\n"); + /* XXX ID + Seq */ + break; + #ifdef ICMP_MASKREQ + case ICMP_MASKREQ: + (void)printf("Address Mask Request\n"); + break; + #endif + #ifdef ICMP_MASKREPLY + case ICMP_MASKREPLY: + (void)printf("Address Mask Reply\n"); + break; + #endif + default: + (void)printf("Bad ICMP type: %d\n", icp->icmp_type); + } + } + + /* + * pr_iph -- + * Print an IP header with options. + */ + static void + pr_iph(struct iphdr *ip) + { + int hlen; + u_char *cp; + + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + 20; /* point to options */ + + (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); + (void)printf(" %1x %1x %02x %04x %04x", + ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); + (void)printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, + (ip->ip_off) & 0x1fff); + (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); + (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_src))); + (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_dst))); + /* dump and option bytes */ + while (hlen-- > 20) { + (void)printf("%02x", *cp++); + } + (void)putchar('\n'); + } + + /* + * pr_addr -- + * Return an ascii host address as a dotted quad and optionally with + * a hostname. + */ + static char * + pr_addr(u_long l) + { + struct hostent *hp; + static char buf[256]; + + if ((options & F_NUMERIC) || + !(hp = gethostbyaddr((char *)&l, 4, AF_INET))) + (void)snprintf(buf, sizeof(buf), "%s", + inet_ntoa(*(struct in_addr *)&l)); + else + (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, + inet_ntoa(*(struct in_addr *)&l)); + return(buf); + } + + /* + * pr_retip -- + * Dump some info on a returned (via ICMP) IP packet. + */ + static void + pr_retip(struct iphdr *ip) + { + int hlen; + u_char *cp; + + pr_iph(ip); + hlen = ip->ip_hl << 2; + cp = (u_char *)ip + hlen; + + if (ip->ip_p == 6) + (void)printf("TCP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + else if (ip->ip_p == 17) + (void)printf("UDP: from port %u, to port %u (decimal)\n", + (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); + } + + static void + fill(void *bp1, char *patp) + { + register int ii, jj, kk; + int pat[16]; + char *cp, *bp = (char *)bp1; + + for (cp = patp; *cp; cp++) + if (!isxdigit(*cp)) { + (void)fprintf(stderr, + "ping: patterns must be specified as hex digits.\n"); + exit(2); + } + ii = sscanf(patp, + "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", + &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], + &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], + &pat[13], &pat[14], &pat[15]); + + if (ii > 0) + for (kk = 0; kk <= MAXPACKET - (8 + ii); kk += ii) + for (jj = 0; jj < ii; ++jj) + bp[jj + kk] = pat[jj]; + if (!(options & F_QUIET)) { + (void)printf("PATTERN: 0x"); + for (jj = 0; jj < ii; ++jj) + (void)printf("%02x", bp[jj] & 0xFF); + (void)printf("\n"); + } + } + + static void + usage(void) + { + (void)fprintf(stderr, + "usage: ping [-LRdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] [-t ttl] [-I interface address] host\n"); + exit(2); + } diff --git a/src/moralesty1/pong.cpp b/src/moralesty1/pong.cpp new file mode 100644 index 0000000..ce3e284 --- /dev/null +++ b/src/moralesty1/pong.cpp @@ -0,0 +1,989 @@ +/* + +Pong + +Using the Internet Control Message Protocol (ICMP) ECHO_REQUEST +and ECHO_REPLY messages to measure round-trip-delays and packet +loss across network paths. Eventually, we'd like to expand +this to UDP pinging as well. + +Created as a 2013 NDSU Capstone Project with specifications +and requirements provided by Ericsson. + +An extension/reimplementation of the original ping.c for the 21st +century. +Emphasis is on readability and ease of understanding the code. +Inspiration and design inspired by: + +Mike Muuss +U. S. Army Ballistic Research Laboratory +December, 1983 +Modified at UC Berkeley + +*/ + + +/* + +Imports and definitions + +*/ + +#define IP_MINLENGTH 34 +#define ICMP_MINLENGTH 16 +#define DEFAULT_LISTEN_TIMEOUT 2 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __MACH__ +#include +#include +#endif + +#if __unix__||__APPLE__ +#include +#include +#include +#include +#include +#include +#include +#include + +#elif WIN32 +#include +#include +struct sockaddr_in *socketAddress; +/* ICMP Header for Windows branch */ +struct icmp { + BYTE icmp_type; // ICMP packet type + BYTE icmp_code; // Type sub code + USHORT icmp_cksum; + USHORT icmp_id; + USHORT icmp_seq; + ULONG icmp_data; // not part of ICMP, but we need it +}; +#endif + +/* + +Initialize Structs + +*/ + +struct sockaddr_in *whereto; +struct in_addr destIP; +struct in_addr srcIP; +struct icmp * icmpHeader; +struct icmp * receivedICMPHeader; +struct icmp * receivedIPHeader; +struct ip * ipHeader; +u_char * packet[100]; +u_char * packetIP[100]; + +/* + +Global Variables for stats and keeping track +of how many pings were sent, how many need +to be excluded, and more. + +*/ +int sent; +int packetsTimedOut = 0; +int processID; +int icmpPayloadLength = 30; +int pingsToSend = 5; +int pingsSent = 0; +int pingsToExclude = 0; +double totalResponseTime = 0.0; +double sumOfResponseTimesSquared = 0.0; +double roundTripTime = 0.0; +int pingsReceived = 0; +bool excludingPing; +int timeoutInput = DEFAULT_LISTEN_TIMEOUT; +volatile bool killSwitch = true; + +/* + +Variables for CSV file + +*/ +using namespace std; +ofstream csvOutput; +string csvFileName = "output.csv"; + +/* + +Time settings + +*/ + +#if __MACH__ +clock_serv_t cclock; +mach_timespec_t sentTime, receivedTime; +#elif __WINDOWS__ +#elif __GNUC__ +struct timespec sentTime2, receivedTime2; +#endif + + + +/* + +Checksum() + +Simple checksum function for ICMP Header. This implentation was +adapted from Mike Musss' version of ping.c + +*/ +static u_short checksum(u_short *ICMPHeader, int len) +{ + register int nleft = len; + register u_short *ICMPPointer = ICMPHeader; + register int sum = 0; + u_short answer = 0; + + /* + Our algorithm is simple, using a 32 bit accumulator (sum), we add + sequential 16 bit words to it, and at the end, fold back all the + carry bits from the top 16 bits into the lower 16 bits. + */ + while (nleft > 1) + { + sum += *ICMPPointer; + ICMPPointer++; + nleft -= 2; + } + + /* Mop up an odd byte, if necessary */ + if (nleft == 1) + { + *(u_char *)(&answer) = *(u_char *) ICMPPointer; + sum += answer; + } + + /* Add back carry outs from top 16 bits to low 16 bits */ + sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ + sum += (sum >> 16); /* add carry */ + answer = (u_short)~sum; /* truncate to 16 bits */ + return(answer); +} + +/* + +pingICMP() + +This method actually sends our ECHO_REQUEST across the internet. +It computes the ICMP checksum and sends the packet to the address +specified in main(). + +*/ +void pingICMP(int socketDescriptor, int icmpPayloadLength) +{ + /* Get time, put it in the packet */ + + /* Set time sent */ + #ifdef __MACH__ + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, (mach_timespec_t *)icmpHeader->icmp_data); + mach_port_deallocate(mach_task_self(), cclock); + + #elif __WINDOWS__ + // GetTick64Count() + #elif __GNUC__ + clock_gettime(CLOCK_MONOTONIC, (struct timespec *)icmpHeader->icmp_data); + #else + //clock_gettime(CLOCK_REALTIME, &ts); + #endif + + /* Compute checksum */ + icmpHeader->icmp_cksum = 0; + icmpHeader->icmp_cksum = checksum((u_short *)icmpHeader, sizeof(*icmpHeader)); + + /* Try to send the packet */ + sent = sendto(socketDescriptor, packet, icmpPayloadLength + 8, 0, (struct sockaddr *)whereto, sizeof(struct sockaddr)); + + /* Check if the packet sent or not */ + if(sent > 0) + { + pingsSent++; + /* Increment the packet sequence number */ + icmpHeader->icmp_seq++; + } + else + { + printf("Ping not sent.\n\n"); + } +} + +/* + +report() + +This function reports the final statistics, either to the command line +or to a CSV (comma separated value) file. Current statistics and output +information includes pings sent, pings received, pings dropped, pings excluded, +average response time, and standard deviation for response time. + +*/ +void report() +{ + if(pingsSent != 0) + { + printf("----------------------------------------------------------------\n"); + printf("%d packets sent, %d dropped", pingsSent, (pingsSent - pingsReceived)); + if(excludingPing) + { + printf(", %d excluded from summary\n", pingsToExclude); + } + else + { + printf("\n"); + } + double average = totalResponseTime / (pingsSent - pingsToExclude); + printf("Stats avg/stddev : %f / %f\n", average, sqrt((sumOfResponseTimesSquared / (pingsReceived - pingsToExclude)) - (average * average))); + printf("----------------------------------------------------------------\n"); + } +} + +/* + +listenICMP() + +This function waits from an incoming packet, checks to see if it is our ECHO_REPLY, +and then gets data out of the packet and computes statistics or doesn't (depending +on if we're excluding that response or not). + +*/ +void listenICMP(int socketDescriptor, sockaddr_in * fromWhom, bool quiet, bool excludingPings, int timeoutLength) +{ + /* Setting some variables needed for select() and our file descriptor */ + char receivedPacketBuffer[512]; + fd_set readfds; + FD_SET(socketDescriptor, &readfds); + struct timeval timeout; + timeout.tv_sec = timeoutLength; // timeout period, seconds (added second, if that matters) + //printf("Timeout length") + timeout.tv_usec = 0; // timeuot period, microseconds 1,000,000 micro = second + // TODO Make this timeout dependent on how many pings have been sent... + int selectStatus = select(socketDescriptor+1, &readfds, NULL, NULL, &timeout); + socklen_t fromWhomLength = sizeof(fromWhom); + if(selectStatus == -1) + { + printf("LISTEN: Error in select()\n"); + } + else if(selectStatus == 0) + { + printf("I'm tired of waiting. Timeout.\n"); + packetsTimedOut++; + csvOutput << "Dropped" << endl; + return; + } + else + { + if(FD_ISSET(socketDescriptor, &readfds)) + { + + /* Receive the data */ + ssize_t bytesReceived = recvfrom(socketDescriptor, receivedPacketBuffer, sizeof(receivedPacketBuffer), 0, (struct sockaddr *)&fromWhom, &fromWhomLength); + + /* Format the received data into the IP struct, then shift bits */ + struct ip * receivedIPHeader = (struct ip *) receivedPacketBuffer; + int headerLength = receivedIPHeader->ip_hl << 2; + + /* Format the received data into the ICMP struct */ + receivedICMPHeader = (struct icmp *)(receivedPacketBuffer + headerLength); + + /* Get the time */ + #if __MACH__ + clock_get_time(cclock, &receivedTime); + mach_timespec_t * sentTime = (mach_timespec_t *)receivedICMPHeader->icmp_data; + /* Thanks Richard Stevens' book UNIX Network Programming for helping with + this next chunk of time processing code */ + if ( (receivedTime.tv_nsec -= sentTime->tv_nsec) < 0) + { + --receivedTime.tv_sec; + receivedTime.tv_nsec += 1000000000; + } + + #elif __WINDOWS__ + // GetTick64Count() + #elif __GNUC__ + clock_gettime(CLOCK_MONOTONIC, &receivedTime2); + struct timespec * sentTime2 = (struct timespec *)receivedICMPHeader->icmp_data; + /* Thanks Richard Stevens' book UNIX Network Programming for helping with + this next chunk of time processing code */ + if ( (receivedTime2.tv_nsec -= sentTime2->tv_nsec) < 0) + { + --receivedTime2.tv_sec; + receivedTime2.tv_nsec += 1000000000; + } + + #endif + + /* Check if the packet was an ECHO_REPLY, and if it was meant for our computer using the ICMP id, + which we set to the process ID */ + if (receivedICMPHeader->icmp_type == 0) + { + + if(receivedICMPHeader->icmp_id != processID) + { + printf("Not our packet\n"); + printf("processID = %d \t ID = %d\n", processID, receivedICMPHeader->icmp_id); + } + else + { + /* We got a valid reply. Count it! */ + pingsReceived++; + + /* Calculate round trip time */ + if(!excludingPings) + { + #if __MACH__ + receivedTime.tv_sec -= sentTime->tv_sec; + roundTripTime = receivedTime.tv_sec * 1000.0 + receivedTime.tv_nsec / 1000000.0; + #elif __GNUC__ + receivedTime2.tv_sec -= sentTime2->tv_sec; + roundTripTime = receivedTime2.tv_sec * 1000.0 + receivedTime2.tv_nsec / 1000000.0; + #endif + sumOfResponseTimesSquared += roundTripTime * roundTripTime; + totalResponseTime += roundTripTime; + } + + /* Get presentation format of source IP */ + char str[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(receivedIPHeader->ip_src), str, INET_ADDRSTRLEN); + + /* If we're counting stats for this reply, add data to running stats */ + if(!excludingPings) + { + /* If we're in CSV mode, print info to the file instead of to the terminal */ + if(quiet) + { + printf(".\n"); + csvOutput << (bytesReceived + 14) << "," << str << "," << receivedICMPHeader->icmp_seq << "," << (int)receivedIPHeader->ip_ttl << "," << roundTripTime << endl; + } + /* Otherwise, print received reply information to the terminal */ + else + { + printf("%d bytes from %s packet number:%d ttl:%d time:%f ms\n", (bytesReceived + 14), str, receivedICMPHeader->icmp_seq, (int)receivedIPHeader->ip_ttl, roundTripTime); + } + } + } + } + } + } +} + + +/* + +buildPing() + +buildPing() initializes the ICMP Header and IP Header structs, which +contain essential packet information. The IP address information is +set in main(). + +*/ +void buildPing() +{ + icmpHeader = (struct icmp *) packet; + ipHeader= (struct ip *) packetIP; + icmpHeader->icmp_type = 8; // This shouldn't change + icmpHeader->icmp_code = 0; + icmpHeader->icmp_cksum = 0; + icmpHeader->icmp_seq = 1; + icmpHeader->icmp_id = processID; + ipHeader->ip_p = 1; + ipHeader->ip_ttl = 64; //Recommended value, according to the internet. + ipHeader->ip_hl = 5; +} + + +void interrupt(int signal); +/* + +main() + +Where the magic happens. Command line flags are set, program +control is set. + +*/ +char *argv[2]; +int main(int argc, const char** argv) +{ + signal(SIGINT, interrupt); + #ifdef WIN32 + WSADATA wsaData; + int result=WSAStartup(MAKEWORD(2,0), &wsaData); + if(result != 0) { + printf("WSAStartup failed with error: %d\n", wsaData); + return 1; + #endif + printf("----------------------------------------------------------------\n"); + + int socketDescriptor; + + /* + + Variables for command line flag processing + + */ + const char* destination = argv[1]; + bool timeBetweenReq = 0; // -q // --request-time + float msecsBetweenReq = 1000; + bool timeBetweenRepReq = 0; // -b // --reply-request-time + int msecsBetweenRepReq = 0; + bool datagramSizeSet = 0; // -d // --datagram-size + bool payloadSize = 0; // -p // --payload-size + bool randSizeMinMax = 0; // -l // --random-size-minmax + int bytesSizeMin = 0; + int bytesSizeMax = 0; + bool randSizeAvgStd = 0; // -r // --random-size-avgstd + int bytesSizeAvg = 0; + int bytesSizeStd = 0; + bool randTimeMinMax = 0; // -s // --random-time-minmax + int msecsTimeMin = 0; + int msecsTimeMax = 0; + bool randTimeAvgStd = 0; // -t // --random-time-avgstd + int msecsTimeAvg = 0; + int msecsTimeStd = 0; + bool increasingSize = 0; // -i // --increasing-size + int sizeInitial = 0; // Must be greater than or equal to (IP_MINLENGTH + ICMP_MINLENGTH) + int sizeGrowth = 0; + excludingPing = 0; // -e // --exclud + bool multiplePings = 0; // -n // --ping-count + bool csvMode = 0; // -c // --csv + + if(argc - 1 == 0) + { + printf("USAGE:\nePing [host IP or domain name]\n[-n/--pings-to-send num of pings to send]\n[-e/--exclude num of pings to exclude from stats]\n\nTIME\n[-q/--request-time time between sent pings]\n[-t/--random-time-avgstd set random, normally distributed time between pings - enter average and standard deviation]\n[-z/--timeout manually set timeout for listening method]\n\nSIZE\n[-p/--payload-size ICMP payload size] OR [-d/--datagram-size size of whole packet]\n[-r/--random-size-avgstd set random, normally distributed packet sizes - enter average and standard deviation]\n\nOUTPUT\n[-c/--csv output reply information to a csv file]\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + else + { + + /* Check if we're root. If not, we can't create the raw socket necessary for ICMP */ + if(getuid()!=0 && geteuid()!=0) + { + printf("UID: %d EUID: %d", getuid(), geteuid()); + printf("\nCan't run. I need root permissions to create raw socket. Sorry.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + + /* Create socket descriptor for sending and receiving traffic */ + socketDescriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); + + /* Drop root permissions */ + seteuid(501); + setuid(getuid()); + + } + for(int i = 2; i < argc; i++) { + // argv[0] is the ./a which is input + // argv[1] is the address (IPv4, DNS, IPv6) + if(strcmp(argv[i],"-q") == 0 || strcmp(argv[i],"--request-time") == 0) + { + if(timeBetweenRepReq || randTimeMinMax || randTimeAvgStd) + { + printf("-q flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + timeBetweenReq = true; + msecsBetweenReq = atoi(argv[i + 1]); + printf("Flag -q set! Waiting %f milliseconds between ping requests.\n", msecsBetweenReq); + i++; + } + else + { + printf("-q flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--reply-request-time") == 0) + { + if(timeBetweenReq || randTimeMinMax || randTimeAvgStd) + { + printf("-b flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + timeBetweenRepReq = true; + msecsBetweenRepReq = atoi(argv[i + 1]); + printf("Flag -b set! Waiting %d milliseconds between receiving a reply and sending a request\n", msecsBetweenRepReq); + i++; + } + else + { + printf("-b flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--datagram-size") == 0) + { + if(payloadSize || randSizeMinMax || randSizeAvgStd) + { + printf("-d flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + datagramSizeSet = true; + icmpPayloadLength = atoi(argv[i + 1]) - ICMP_MINLEN - IP_MINLENGTH; + if(icmpPayloadLength < 8) + { + printf("Error: datagram size must be greater than 50 bytes.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + printf("Flag -d set! Datagram will be %d bytes large.\n", icmpPayloadLength+IP_MINLENGTH+ICMP_MINLEN); + i++; + } + else + { + printf("-d flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--payload-size") == 0) + { + if(datagramSizeSet || randSizeMinMax || randSizeAvgStd) + { + printf("-p flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 1 < argc && atoi(argv[i + 1]) >= 0) + { + payloadSize = true; + icmpPayloadLength = atoi(argv[i + 1]); + if(icmpPayloadLength < 8) + { + printf("Error: Payload size must be 8 bytes or greater.\n"); + printf("----------------------------------------------------------------\n"); + return(1); + } + printf("Flag -p set! Payload size will be %d bytes large.\n", icmpPayloadLength); + i++; + } + else + { + printf("-p flag not set, requires parameter.\n"); + } + } + } + else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--random-size-minmax") == 0) + { + if(datagramSizeSet || payloadSize || increasingSize || randSizeAvgStd) + { + printf("-l flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randSizeMinMax = true; + if(atoi(argv[i + 1]) > atoi(argv[i + 2])) + { + bytesSizeMin = atoi(argv[i + 2]); + bytesSizeMax = atoi(argv[i + 1]); + } + else + { + bytesSizeMin = atoi(argv[i + 1]); + bytesSizeMax = atoi(argv[i + 2]); + } + printf("Flag -l set! Random size will be between %d ", bytesSizeMin); + printf("and %d.\n", bytesSizeMax); + i += 2; + } + else + { + printf("-l flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-r") == 0 || strcmp(argv[i],"--random-size-avgstd") == 0) + { + if(datagramSizeSet || payloadSize || increasingSize || randSizeMinMax) + { + printf("-r flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randSizeAvgStd = true; + bytesSizeAvg = atoi(argv[i + 1]); + bytesSizeStd = atoi(argv[i + 2]); + printf("Flag -r set! Random size will average %d",bytesSizeAvg); + printf(" with a std. dev. of %d.\n", bytesSizeStd); + i += 2; + } + else + { + printf("-r flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--random-time-minmax") == 0) + { + if(timeBetweenReq || timeBetweenRepReq || randTimeAvgStd) + { + printf("-s flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randTimeMinMax = true; + if(atoi(argv[i + 1]) > atoi(argv[i + 2])) + { + msecsTimeMin = atoi(argv[i + 2]); + msecsTimeMax = atoi(argv[i + 1]); + } + else + { + msecsTimeMin = atoi(argv[i + 1]); + msecsTimeMax = atoi(argv[i + 2]); + } + printf("Flag -s set! Random time between requests will be between %d ", msecsTimeMin); + printf("and %d.\n", msecsTimeMax); + i += 2; + } + else + { + printf("-s flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-t") == 0 || strcmp(argv[i],"--random-time-avgstd") == 0) + { + if(timeBetweenReq || timeBetweenRepReq || randTimeMinMax) + { + printf("-t flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + randTimeAvgStd = true; + msecsTimeAvg = atoi(argv[i + 1]); + msecsTimeStd = atoi(argv[i + 2]); + printf("Flag -t set! Random time between requests will average %d ",msecsTimeAvg); + printf("with a std. dev. of %d.\n", msecsTimeStd); + i += 2; + } + else + { + printf("-t flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--increasing-size") == 0) + { + if(datagramSizeSet || payloadSize || randSizeMinMax || randSizeAvgStd) + { + printf("-i flag not set, conflicting with previously set flag.\n"); + } + else + { + if(i + 2 < argc && atoi(argv[i + 2]) > 0) + { + increasingSize = true; + sizeInitial = atoi(argv[i + 1]); + sizeGrowth = atoi(argv[i + 2]); + if(sizeInitial >= (IP_MINLENGTH + ICMP_MINLENGTH)) + { + printf("Flag -i set! Pings will have an initial size of %d ", sizeInitial); + printf("and grow at a rate of %d per request.\n", sizeGrowth); + + //Subtract growth from initial once so when we ping, we can add sizeGrowth to it every time, + //and initialGrowth is still proper + icmpPayloadLength = sizeInitial - sizeGrowth - IP_MINLENGTH - ICMP_MINLENGTH + 8; + } + else + { + printf("Problem: Initial size must be greater than IP header size plus the ICMP header size (%d).\n", IP_MINLENGTH + ICMP_MINLENGTH); + return(1); + } + i += 2; + } + else + { + printf("-i flag not set, requires parameters.\n"); + } + } + } + else if(strcmp(argv[i],"-e") == 0 || strcmp(argv[i],"--exclude") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + excludingPing = true; + pingsToExclude = atoi(argv[i + 1]); + if(pingsToExclude >= pingsToSend) + { + printf("Trying to exclude more pings than you send huh? Not funny.\n"); + exit(0); + } + printf("Flag -e set! %d earliest pings to be excluded from final statistics.\n", pingsToExclude); + i++; + } + else + { + printf("-e flag not set, requires parameter.\n"); + } + + } + else if(strcmp(argv[i],"-n") == 0 || strcmp(argv[i],"--pings-to-send") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + multiplePings = true; + pingsToSend = atoi(argv[i + 1]); + printf("Flag -n set! %d pings to be sent.\n", pingsToSend); + i++; + } + else + { + printf("-n flag not set, requires parameter.\n"); + + } + + } + else if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--csv") == 0) + { + csvMode = 1; + if(i + 1 < argc) + { + csvFileName = argv[i+1]; + i++; + } + else + { + csvFileName = "output.csv"; + } + /* Open the CSV file */ + csvOutput.open(csvFileName); + printf("Flag -c set! Replies will be output to %s.\n", csvFileName.c_str()); + } + else if(strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--timeout") == 0) + { + if(i + 1 < argc && atoi(argv[i + 1]) > 0) + { + timeoutInput = atoi(argv[i + 1]); + i++; + } + + printf("Flag -z set! Listening timeout will be set to %d seconds.\n", timeoutInput); + } + else + { + printf("Flag not recognized, \"%s\"\n",argv[i]); + } + } + printf("Destination set to: %s\n", argv[1]); + + struct addrinfo *result, hints; + hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_RAW; /* RAW socket */ + hints.ai_flags = AI_PASSIVE; /* Fill in my IP address */ + int status; + + /* Convert address */ + if((status = getaddrinfo(destination, NULL, &hints, &result)) != 0) + { + printf("getaddrinfo error: %s\n", gai_strerror(status)); + printf("Double check the address that you want to ping.\n"); + exit(1); + } + + whereto = (struct sockaddr_in *)result->ai_addr; + + + /* + + WINDOWS block for setting the source and destination IP address + + */ + #if WIN32 + sockAddress = &whereto; + int sizeOfAddress=sizeof(IPHeader.destinationIPAddress); + if(WSAStringToAddress((char *)destination,AF_INET,NULL,(LPSOCKADDR)&IPHeader.destinationIPAddress.S_un.S_un_W,&sizeOfAddress)!=0) + { + int error=WSAGetLastError(); + std::cout<sin_addr),(int*)sizeof(socketAddress->sin_addr))!=0) + { + int error=WSAGetLastError(); + std::cout< distribution(bytesSizeAvg, bytesSizeStd); + std::normal_distribution distribution2(msecsTimeAvg, msecsTimeStd); + + + /* Specify that we want two threads (one for listening, one for sending) */ + omp_set_num_threads(2); + + /* + + Execute the ping/listen functions in sequential mode (wait for reply before sending request) + + */ + if(timeBetweenRepReq) + { + while(pingsSent < pingsToSend) + { + + pingICMP(socketDescriptor, icmpPayloadLength); + listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); + usleep(msecsBetweenRepReq * 1000); + } + + } + + /* + + Execute the ping/listen functions in parallel with OpenMP threading + + */ + else + { + + #pragma omp parallel sections + { + + /* Sending block */ + #pragma omp section + for (i = 0; i < pingsToSend; i++) + { + /* Ping */ + if(randSizeAvgStd) + { + randomDatagramSize = distribution(generator); + pingICMP(socketDescriptor, randomDatagramSize - IP_MINLENGTH - ICMP_MINLEN); + } + else if(increasingSize) + { + icmpPayloadLength += sizeGrowth; + pingICMP(socketDescriptor, icmpPayloadLength); + } + else + { + pingICMP(socketDescriptor, icmpPayloadLength); + } + + /* Wait */ + if(randTimeAvgStd) + { + randomTime = distribution2(generator); + usleep(randomTime * 1000); + } + else + { + usleep(msecsBetweenReq * 1000); + } + } + + /* Listening block */ + #pragma omp section + while(i != pingsToSend - 1 && pingsToSend != pingsReceived + packetsTimedOut && killSwitch) + { + + /* If we're excluding some pings, listen but don't print any info */ + if(excludingPing && pingsReceived < pingsToExclude) + { + listenICMP(socketDescriptor, &sourceSocket, 1, 1, timeoutInput); + } + + /* If we're outputting to a CSV file, don't print out so much on the terminal */ + else if(csvMode) + { + listenICMP(socketDescriptor, &sourceSocket, 1, 0, timeoutInput); + } + + /* Otherwise, print all statistics and information to the terminal */ + else + { + listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); + } + + } + + } + } + + /* Print final statistics and quit */ + report(); + + if(csvMode) + { + csvOutput.close(); + } + #ifdef WIN32 + int result = WSACleanup(); + #endif + return(0); + } + + void interrupt(int signal) + { + if(killSwitch) + { + pingsToSend = 0; + killSwitch = false; + } + } From 1ddcbc4058de27ba5aef134b98f075bf3630e99f Mon Sep 17 00:00:00 2001 From: moralesty1 Date: Tue, 12 May 2015 10:25:26 -0500 Subject: [PATCH 6/7] Fixed Assinment-one --- res/moralesty1/picture.png | Bin 0 -> 18065 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 res/moralesty1/picture.png diff --git a/res/moralesty1/picture.png b/res/moralesty1/picture.png new file mode 100644 index 0000000000000000000000000000000000000000..0524a970628c02b90fd22dd6a7b0d83c0bb37d31 GIT binary patch literal 18065 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 Date: Tue, 12 May 2015 10:30:06 -0500 Subject: [PATCH 7/7] added deleted files --- res/.DS_Store | Bin 6148 -> 0 bytes res/moralesty1/.DS_Store | Bin 6148 -> 0 bytes res/moralesty1/ping.c | 1175 -------------------------------------- res/moralesty1/pong.cpp | 968 ------------------------------- res/picture.png | Bin 18065 -> 0 bytes 5 files changed, 2143 deletions(-) delete mode 100644 res/.DS_Store delete mode 100644 res/moralesty1/.DS_Store delete mode 100644 res/moralesty1/ping.c delete mode 100644 res/moralesty1/pong.cpp delete mode 100644 res/picture.png diff --git a/res/.DS_Store b/res/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0Ya1Z+}TZfPa>2TO>8wLc(w^w_! z7n|1er9R=;@a5@*$QS9YJ99DaNBfa~4<~<-d<=c$p8QV diff --git a/res/moralesty1/ping.c b/res/moralesty1/ping.c deleted file mode 100644 index c6102fc..0000000 --- a/res/moralesty1/ping.c +++ /dev/null @@ -1,1175 +0,0 @@ -/* -* Copyright (c) 1989 The Regents of the University of California. -* All rights reserved. -* -* This code is derived from software contributed to Berkeley by -* Mike Muuss. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* 1. Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* 2. Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in the -* documentation and/or other materials provided with the distribution. -* 3. All advertising materials mentioning features or use of this software -* must display the following acknowledgement: -* This product includes software developed by the University of -* California, Berkeley and its contributors. -* 4. Neither the name of the University nor the names of its contributors -* may be used to endorse or promote products derived from this software -* without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -* SUCH DAMAGE. -*/ - -char copyright[] = -"@(#) Copyright (c) 1989 The Regents of the University of California.\n" -"All rights reserved.\n"; -/* -* From: @(#)ping.c 5.9 (Berkeley) 5/12/91 -*/ -char rcsid[] = "$Id: ping.c,v 1.22 1997/06/08 19:39:47 dholland Exp $"; -char pkg[] = "netkit-base-0.10"; - -/* -* P I N G . C -* -* Using the InterNet Control Message Protocol (ICMP) "ECHO" facility, -* measure round-trip-delays and packet loss across network paths. -* -* Author - -* Mike Muuss -* U. S. Army Ballistic Research Laboratory -* December, 1983 -* -* Status - -* Public Domain. Distribution Unlimited. -* Bugs - -* More statistics could always be gathered. -* This program has to run SUID to ROOT to access the ICMP socket. -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* -* Note: on some systems dropping root makes the process dumpable or -* traceable. In that case if you enable dropping root and someone -* traces ping, they get control of a raw socket and can start -* spoofing whatever packets they like. SO BE CAREFUL. -*/ -#ifdef __linux__ -#define SAFE_TO_DROP_ROOT -#endif - -#if defined(__GLIBC__) && (__GLIBC__ >= 2) -#define icmphdr icmp -#define ICMP_DEST_UNREACH ICMP_UNREACH -#define ICMP_NET_UNREACH ICMP_UNREACH_NET -#define ICMP_HOST_UNREACH ICMP_UNREACH_HOST -#define ICMP_PORT_UNREACH ICMP_UNREACH_PORT -#define ICMP_PROT_UNREACH ICMP_UNREACH_PROTOCOL -#define ICMP_FRAG_NEEDED ICMP_UNREACH_NEEDFRAG -#define ICMP_SR_FAILED ICMP_UNREACH_SRCFAIL -#define ICMP_NET_UNKNOWN ICMP_UNREACH_NET_UNKNOWN -#define ICMP_HOST_UNKNOWN ICMP_UNREACH_HOST_UNKNOWN -#define ICMP_HOST_ISOLATED ICMP_UNREACH_ISOLATED -#define ICMP_NET_UNR_TOS ICMP_UNREACH_TOSNET -#define ICMP_HOST_UNR_TOS ICMP_UNREACH_TOSHOST -#define ICMP_SOURCE_QUENCH ICMP_SOURCEQUENCH -#define ICMP_REDIR_NET ICMP_REDIRECT_NET -#define ICMP_REDIR_HOST ICMP_REDIRECT_HOST -#define ICMP_REDIR_NETTOS ICMP_REDIRECT_TOSNET -#define ICMP_REDIR_HOSTTOS ICMP_REDIRECT_TOSHOST -#define ICMP_TIME_EXCEEDED ICMP_TIMXCEED -#define ICMP_EXC_TTL ICMP_TIMXCEED_INTRANS -#define ICMP_EXC_FRAGTIME ICMP_TIMXCEED_REASS -#define ICMP_PARAMETERPROB ICMP_PARAMPROB -#define ICMP_TIMESTAMP ICMP_TSTAMP -#define ICMP_TIMESTAMPREPLY ICMP_TSTAMPREPLY -#define ICMP_INFO_REQUEST ICMP_IREQ -#define ICMP_INFO_REPLY ICMP_IREQREPLY -#else -#define ICMP_MINLEN 28 -#define inet_ntoa(x) inet_ntoa(*((struct in_addr *)&(x))) -#endif - - -#define DEFDATALEN (64 - 8) /* default data length */ -#define MAXIPLEN 60 -#define MAXICMPLEN 76 -#define MAXPACKET (65536 - 60 - 8)/* max packet size */ -#define MAXWAIT 10 /* max seconds to wait for response */ -#define NROUTES 9 /* number of record route slots */ - -#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)) - -/* various options */ -int options; -#define F_FLOOD 0x001 -#define F_INTERVAL 0x002 -#define F_NUMERIC 0x004 -#define F_PINGFILLED 0x008 -#define F_QUIET 0x010 -#define F_RROUTE 0x020 -#define F_SO_DEBUG 0x040 -#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 -* to 8192 for complete accuracy... -*/ -#define MAX_DUP_CHK (8 * 128) -int mx_dup_ck = MAX_DUP_CHK; -char rcvd_tbl[MAX_DUP_CHK / 8]; - -struct sockaddr whereto; /* who to ping */ -int datalen = DEFDATALEN; -int s; /* socket file descriptor */ -u_char outpack[MAXPACKET]; -char BSPACE = '\b'; /* characters written for flood */ -char DOT = '.'; -static char *hostname; -static int ident; /* process id to identify our packets */ - - - -/* timing */ -static int timing; /* flag to do timing */ -static long tmin = LONG_MAX; /* minimum round trip time */ -static long tmax = 0; /* maximum round trip time */ -static u_long tsum; /* sum of all times, for doing average */ - - - - -int -main(int argc, char *argv[]) -{ - struct timeval timeout; - struct hostent *hp; - struct sockaddr_in *to; - struct protoent *proto; - struct in_addr ifaddr; - int i; - int ch, fdmask, hold, packlen, preload; - u_char *datap, *packet; - char *target, hnamebuf[MAXHOSTNAMELEN]; - u_char ttl, loop; - int am_i_root; - #ifdef IP_OPTIONS - char rspace[3 + 4 * NROUTES + 1]; /* record route space */ - #endif - - static char *null = NULL; - __environ = &null; - am_i_root = (getuid()==0); - - /* - * Pull this stuff up front so we can drop root if desired. - */ - if (!(proto = getprotobyname("icmp"))) { - (void)fprintf(stderr, "ping: unknown protocol icmp.\n"); - exit(2); - } - if ((s = socket(AF_INET, SOCK_RAW, proto->p_proto)) < 0) { - if (errno==EPERM) { - fprintf(stderr, "ping: ping must run as root\n"); - } - else perror("ping: socket"); - exit(2); - } - - #ifdef SAFE_TO_DROP_ROOT - setuid(getuid()); - #endif - - preload = 0; - datap = &outpack[8 + sizeof(struct timeval)]; - while ((ch = getopt(argc, argv, "I:LRc:dfh:i:l:np:qrs:t:v")) != EOF) - switch(ch) { - case 'c': - npackets = atoi(optarg); - if (npackets <= 0) { - (void)fprintf(stderr, - "ping: bad number of packets to transmit.\n"); - exit(2); - } - break; - case 'd': - options |= F_SO_DEBUG; - break; - case 'f': - if (!am_i_root) { - (void)fprintf(stderr, - "ping: %s\n", strerror(EPERM)); - exit(2); - } - options |= F_FLOOD; - setbuf(stdout, NULL); - break; - case 'i': /* wait between sending packets */ - interval = atoi(optarg); - if (interval <= 0) { - (void)fprintf(stderr, - "ping: bad timing interval.\n"); - exit(2); - } - options |= F_INTERVAL; - break; - case 'l': - if (!am_i_root) { - (void)fprintf(stderr, - "ping: %s\n", strerror(EPERM)); - exit(2); - } - preload = atoi(optarg); - if (preload < 0) { - (void)fprintf(stderr, - "ping: bad preload value.\n"); - exit(2); - } - break; - case 'n': - options |= F_NUMERIC; - break; - case 'p': /* fill buffer with user pattern */ - options |= F_PINGFILLED; - fill(datap, optarg); - break; - case 'q': - options |= F_QUIET; - break; - case 'R': - options |= F_RROUTE; - break; - case 'r': - options |= F_SO_DONTROUTE; - break; - case 's': /* size of packet to send */ - datalen = atoi(optarg); - if (datalen > MAXPACKET) { - (void)fprintf(stderr, - "ping: packet size too large.\n"); - exit(2); - } - if (datalen <= 0) { - (void)fprintf(stderr, - "ping: illegal packet size.\n"); - exit(2); - } - break; - 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(2); - } - ttl = i; - break; - case 'I': - moptions |= MULTICAST_IF; - { - int i1, i2, i3, i4; - char junk; - - if (sscanf(optarg, "%u.%u.%u.%u%c", - &i1, &i2, &i3, &i4, &junk) != 4) { - printf("bad interface address '%s'\n", - optarg); - exit(2); - } - 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; - - memset(&whereto, 0, sizeof(struct sockaddr)); - to = (struct sockaddr_in *)&whereto; - to->sin_family = AF_INET; - if (inet_aton(target, &to->sin_addr)) { - hostname = target; - } - else { - hp = gethostbyname(target); - if (!hp) { - (void)fprintf(stderr, - "ping: unknown host %s\n", target); - exit(2); - } - to->sin_family = hp->h_addrtype; - if (hp->h_length > (int)sizeof(to->sin_addr)) { - hp->h_length = sizeof(to->sin_addr); - } - memcpy(&to->sin_addr, hp->h_addr, hp->h_length); - (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1); - hostname = hnamebuf; - } - - if (options & F_FLOOD && options & F_INTERVAL) { - (void)fprintf(stderr, - "ping: -f and -i incompatible options.\n"); - exit(2); - } - - if (datalen >= (int)sizeof(struct timeval)) /* can we time transfer */ - timing = 1; - packlen = datalen + MAXIPLEN + MAXICMPLEN; - packet = malloc((u_int)packlen); - if (!packet) { - (void)fprintf(stderr, "ping: out of memory.\n"); - exit(2); - } - if (!(options & F_PINGFILLED)) - for (i = 8; i < datalen; ++i) - *datap++ = i; - - ident = getpid() & 0xFFFF; - hold = 1; - - if (options & F_SO_DEBUG) - (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold, - sizeof(hold)); - - if (options & F_SO_DONTROUTE) - (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold, - sizeof(hold)); - - /* this is necessary for broadcast pings to work */ - setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char *)&hold, sizeof(hold)); - - /* record route option */ - if (options & F_RROUTE) { - #ifdef IP_OPTIONS - memset(rspace, 0, sizeof(rspace)); - rspace[IPOPT_OPTVAL] = IPOPT_RR; - rspace[IPOPT_OLEN] = sizeof(rspace)-1; - rspace[IPOPT_OFFSET] = IPOPT_MINOFF; - if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace, - sizeof(rspace)) < 0) { - perror("ping: record route"); - exit(2); - } - #else - (void)fprintf(stderr, - "ping: record route not available in this implementation.\n"); - exit(2); - #endif /* IP_OPTIONS */ - } - - /* - * When pinging the broadcast address, you can get a lot of answers. - * Doing something so evil is useful if you are trying to stress the - * ethernet, or just want to fill the arp cache to get some stuff for - * /etc/ethers. - */ - hold = 48 * 1024; - (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold, - sizeof(hold)); - - /*#if 0*/ - 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); - } - } - /*#endif*/ - - 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), - datalen); - else - (void)printf("PING %s: %d data bytes\n", hostname, datalen); - - (void)signal(SIGINT, finish); - (void)signal(SIGALRM, catcher); - - while (preload--) /* fire off them quickies */ - pinger(); - - if ((options & F_FLOOD) == 0) - catcher(0); /* start things going */ - - for (;;) { - struct sockaddr_in from; - register int cc; - size_t fromlen; - - if (options & F_FLOOD) { - pinger(); - timeout.tv_sec = 0; - timeout.tv_usec = 10000; - fdmask = 1 << s; - if (select(s + 1, (fd_set *)&fdmask, (fd_set *)NULL, - (fd_set *)NULL, &timeout) < 1) - continue; - } - fromlen = sizeof(from); - if ((cc = recvfrom(s, (char *)packet, packlen, 0, - (struct sockaddr *)&from, &fromlen)) < 0) { - if (errno == EINTR) - continue; - perror("ping: recvfrom"); - continue; - } - pr_pack((char *)packet, cc, &from); - if (npackets && nreceived >= npackets) - break; - } - finish(0); - /* NOTREACHED */ - return 0; - } - - /* - * catcher -- - * This routine causes another PING to be transmitted, and then - * schedules another SIGALRM for 1 second from now. - * - * bug -- - * Our sense of time will slowly skew (i.e., packets will not be - * launched exactly at 1-second intervals). This does not affect the - * quality of the delay and loss statistics. - */ - static void - catcher(int ignore) - { - int waittime; - - (void)ignore; - pinger(); - (void)signal(SIGALRM, catcher); - if (!npackets || ntransmitted < npackets) - alarm((u_int)interval); - else { - if (nreceived) { - waittime = 2 * tmax / 1000; - if (!waittime) - waittime = 1; - if (waittime > MAXWAIT) - waittime = MAXWAIT; - } else - waittime = MAXWAIT; - (void)signal(SIGALRM, finish); - (void)alarm((u_int)waittime); - } - } - - #if !defined(__GLIBC__) || (__GLIBC__ < 2) - #define icmp_type type - #define icmp_code code - #define icmp_cksum checksum - #define icmp_id un.echo.id - #define icmp_seq un.echo.sequence - #define icmp_gwaddr un.gateway - #endif /* __GLIBC__ */ - - #define ip_hl ihl - #define ip_v version - #define ip_tos tos - #define ip_len tot_len - #define ip_id id - #define ip_off frag_off - #define ip_ttl ttl - #define ip_p protocol - #define ip_sum check - #define ip_src saddr - #define ip_dst daddr - - /* - * pinger -- - * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet - * will be added on by the kernel. The ID field is our UNIX process ID, - * and the sequence number is an ascending integer. The first 8 bytes - * of the data portion are used to hold a UNIX "timeval" struct in VAX - * byte-order, to compute the round-trip time. - */ - static void - pinger(void) - { - register struct icmphdr *icp; - register int cc; - int i; - - icp = (struct icmphdr *)outpack; - icp->icmp_type = ICMP_ECHO; - icp->icmp_code = 0; - icp->icmp_cksum = 0; - icp->icmp_seq = ntransmitted++; - icp->icmp_id = ident; /* ID */ - - CLR(icp->icmp_seq % mx_dup_ck); - - if (timing) - (void)gettimeofday((struct timeval *)&outpack[8], - (struct timezone *)NULL); - - cc = datalen + 8; /* skips ICMP portion */ - - /* compute ICMP checksum here */ - icp->icmp_cksum = in_cksum((u_short *)icp, cc); - - i = sendto(s, (char *)outpack, cc, 0, &whereto, - sizeof(struct sockaddr)); - - if (i < 0 || i != cc) { - if (i < 0) - perror("ping: sendto"); - (void)printf("ping: wrote %s %d chars, ret=%d\n", - hostname, cc, i); - } - if (!(options & F_QUIET) && options & F_FLOOD) - (void)write(STDOUT_FILENO, &DOT, 1); - } - - /* - * pr_pack -- - * Print out the packet, if it came from us. This logic is necessary - * because ALL readers of the ICMP socket get a copy of ALL ICMP packets - * which arrive ('tis only fair). This permits multiple copies of this - * program to be run without having intermingled output (or statistics!). - */ - void - pr_pack(char *buf, int cc, struct sockaddr_in *from) - { - register struct icmphdr *icp; - register int i; - register u_char *cp,*dp; - /*#if 0*/ - register u_long l; - register int j; - static int old_rrlen; - static char old_rr[MAX_IPOPTLEN]; - /*#endif*/ - struct iphdr *ip; - struct timeval tv, *tp; - long triptime = 0; - int hlen, dupflag; - - (void)gettimeofday(&tv, (struct timezone *)NULL); - - /* Check the IP header */ - ip = (struct iphdr *)buf; - hlen = ip->ip_hl << 2; - if (cc < datalen + ICMP_MINLEN) { - if (options & F_VERBOSE) - (void)fprintf(stderr, - "ping: packet too short (%d bytes) from %s\n", cc, - inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr)); - return; - } - - /* Now the ICMP part */ - cc -= hlen; - icp = (struct icmphdr *)(buf + hlen); - if (icp->icmp_type == ICMP_ECHOREPLY) { - if (icp->icmp_id != ident) - return; /* 'Twas not our ECHO */ - ++nreceived; - if (timing) { - #ifndef icmp_data - tp = (struct timeval *)(icp + 1); - #else - tp = (struct timeval *)icp->icmp_data; - #endif - tvsub(&tv, tp); - triptime = tv.tv_sec * 10000 + (tv.tv_usec / 100); - tsum += triptime; - if (triptime < tmin) - tmin = triptime; - if (triptime > tmax) - tmax = triptime; - } - - if (TST(icp->icmp_seq % mx_dup_ck)) { - ++nrepeats; - --nreceived; - dupflag = 1; - } else { - SET(icp->icmp_seq % mx_dup_ck); - dupflag = 0; - } - - if (options & F_QUIET) - return; - - if (options & F_FLOOD) - (void)write(STDOUT_FILENO, &BSPACE, 1); - else { - (void)printf("%d bytes from %s: icmp_seq=%u", cc, - inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr), - icp->icmp_seq); - (void)printf(" ttl=%d", ip->ip_ttl); - if (timing) - (void)printf(" time=%ld.%ld ms", triptime/10, - triptime%10); - if (dupflag) - (void)printf(" (DUP!)"); - /* check the data */ - #ifndef icmp_data - cp = ((u_char*)(icp + 1) + 8); - #else - cp = (u_char*)icp->icmp_data + 8; - #endif - dp = &outpack[8 + sizeof(struct timeval)]; - for (i = 8; i < datalen; ++i, ++cp, ++dp) { - if (*cp != *dp) { - (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", - i, *dp, *cp); - cp = (u_char*)(icp + 1); - for (i = 8; i < datalen; ++i, ++cp) { - if ((i % 32) == 8) - (void)printf("\n\t"); - (void)printf("%x ", *cp); - } - break; - } - } - } - } else { - /* We've got something other than an ECHOREPLY */ - if (!(options & F_VERBOSE)) - return; - (void)printf("%d bytes from %s: ", cc, - pr_addr(from->sin_addr.s_addr)); - pr_icmph(icp); - } - - /*#if 0*/ - /* Display any IP options */ - cp = (u_char *)buf + sizeof(struct iphdr); - - for (; hlen > (int)sizeof(struct iphdr); --hlen, ++cp) - switch (*cp) { - case IPOPT_EOL: - hlen = 0; - break; - case IPOPT_LSRR: - (void)printf("\nLSRR: "); - hlen -= 2; - j = *++cp; - ++cp; - if (j > IPOPT_MINOFF) - for (;;) { - l = *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - if (l == 0) - (void)printf("\t0.0.0.0"); - else - (void)printf("\t%s", pr_addr(ntohl(l))); - hlen -= 4; - j -= 4; - if (j <= IPOPT_MINOFF) - break; - (void)putchar('\n'); - } - break; - case IPOPT_RR: - j = *++cp; /* get length */ - i = *++cp; /* and pointer */ - hlen -= 2; - if (i > j) - i = j; - i -= IPOPT_MINOFF; - if (i <= 0) - continue; - if (i == old_rrlen - && cp == (u_char *)buf + sizeof(struct iphdr) + 2 - && !memcmp((char *)cp, old_rr, i) - && !(options & F_FLOOD)) { - (void)printf("\t(same route)"); - i = ((i + 3) / 4) * 4; - hlen -= i; - cp += i; - break; - } - old_rrlen = i; - memcpy(old_rr, cp, i); - (void)printf("\nRR: "); - for (;;) { - l = *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - l = (l<<8) + *++cp; - if (l == 0) - (void)printf("\t0.0.0.0"); - else - (void)printf("\t%s", pr_addr(ntohl(l))); - hlen -= 4; - i -= 4; - if (i <= 0) - break; - (void)putchar('\n'); - } - break; - case IPOPT_NOP: - (void)printf("\nNOP"); - break; - default: - (void)printf("\nunknown option %x", *cp); - break; - } - /*#endif*/ - if (!(options & F_FLOOD)) { - (void)putchar('\n'); - (void)fflush(stdout); - } - } - - /* - * in_cksum -- - * Checksum routine for Internet Protocol family headers (C Version) - */ - static int - in_cksum(u_short *addr, int len) - { - register int nleft = len; - register u_short *w = addr; - register int sum = 0; - u_short answer = 0; - - /* - * Our algorithm is simple, using a 32 bit accumulator (sum), we add - * sequential 16 bit words to it, and at the end, fold back all the - * carry bits from the top 16 bits into the lower 16 bits. - */ - while (nleft > 1) { - sum += *w++; - nleft -= 2; - } - - /* mop up an odd byte, if necessary */ - if (nleft == 1) { - *(u_char *)(&answer) = *(u_char *)w ; - sum += answer; - } - - /* add back carry outs from top 16 bits to low 16 bits */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = ~sum; /* truncate to 16 bits */ - return(answer); - } - - /* - * tvsub -- - * Subtract 2 timeval structs: out = out - in. Out is assumed to - * be >= in. - */ - static void - tvsub(register struct timeval *out, register struct timeval *in) - { - if ((out->tv_usec -= in->tv_usec) < 0) { - --out->tv_sec; - out->tv_usec += 1000000; - } - out->tv_sec -= in->tv_sec; - } - - /* - * finish -- - * Print out statistics, and give up. - */ - static void - finish(int ignore) - { - (void)ignore; - - (void)signal(SIGINT, SIG_IGN); - (void)putchar('\n'); - (void)fflush(stdout); - (void)printf("--- %s ping statistics ---\n", hostname); - (void)printf("%ld packets transmitted, ", ntransmitted); - (void)printf("%ld packets received, ", nreceived); - if (nrepeats) - (void)printf("+%ld duplicates, ", nrepeats); - if (ntransmitted) - if (nreceived > ntransmitted) - (void)printf("-- somebody's printing up packets!"); - else - (void)printf("%d%% packet loss", - (int) (((ntransmitted - nreceived) * 100) / - ntransmitted)); - (void)putchar('\n'); - if (nreceived && timing) - (void)printf("round-trip min/avg/max = %ld.%ld/%lu.%ld/%ld.%ld ms\n", - tmin/10, tmin%10, - (tsum / (nreceived + nrepeats))/10, - (tsum / (nreceived + nrepeats))%10, - tmax/10, tmax%10); - - if (nreceived==0) exit(1); - exit(0); - } - - #ifdef notdef - static char *ttab[] = { - "Echo Reply", /* ip + seq + udata */ - "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */ - "Source Quench", /* IP */ - "Redirect", /* redirect type, gateway, + IP */ - "Echo", - "Time Exceeded", /* transit, frag reassem + IP */ - "Parameter Problem", /* pointer + IP */ - "Timestamp", /* id + seq + three timestamps */ - "Timestamp Reply", /* " */ - "Info Request", /* id + sq */ - "Info Reply" /* " */ - }; - #endif - - /* - * pr_icmph -- - * Print a descriptive string about an ICMP header. - */ - static void - pr_icmph(struct icmphdr *icp) - { - switch(icp->icmp_type) { - case ICMP_ECHOREPLY: - (void)printf("Echo Reply\n"); - /* XXX ID + Seq + Data */ - break; - case ICMP_DEST_UNREACH: - switch(icp->icmp_code) { - case ICMP_NET_UNREACH: - (void)printf("Destination Net Unreachable\n"); - break; - case ICMP_HOST_UNREACH: - (void)printf("Destination Host Unreachable\n"); - break; - case ICMP_PROT_UNREACH: - (void)printf("Destination Protocol Unreachable\n"); - break; - case ICMP_PORT_UNREACH: - (void)printf("Destination Port Unreachable\n"); - break; - case ICMP_FRAG_NEEDED: - (void)printf("frag needed and DF set\n"); - break; - case ICMP_SR_FAILED: - (void)printf("Source Route Failed\n"); - break; - case ICMP_NET_UNKNOWN: - (void)printf("Network Unknown\n"); - break; - case ICMP_HOST_UNKNOWN: - (void)printf("Host Unknown\n"); - break; - case ICMP_HOST_ISOLATED: - (void)printf("Host Isolated\n"); - break; - case ICMP_NET_UNR_TOS: - printf("Destination Network Unreachable At This TOS\n"); - break; - case ICMP_HOST_UNR_TOS: - printf("Destination Host Unreachable At This TOS\n"); - break; - #ifdef ICMP_PKT_FILTERED - case ICMP_PKT_FILTERED: - (void)printf("Packet Filtered\n"); - break; - #endif - #ifdef ICMP_PREC_VIOLATION - case ICMP_PREC_VIOLATION: - (void)printf("Precedence Violation\n"); - break; - #endif - #ifdef ICMP_PREC_CUTOFF - case ICMP_PREC_CUTOFF: - (void)printf("Precedence Cutoff\n"); - break; - #endif - default: - (void)printf("Dest Unreachable, Unknown Code: %d\n", - icp->icmp_code); - break; - } - /* Print returned IP header information */ - #ifndef icmp_data - pr_retip((struct iphdr *)(icp + 1)); - #else - pr_retip((struct iphdr *)icp->icmp_data); - #endif - break; - case ICMP_SOURCE_QUENCH: - (void)printf("Source Quench\n"); - #ifndef icmp_data - pr_retip((struct iphdr *)(icp + 1)); - #else - pr_retip((struct iphdr *)icp->icmp_data); - #endif - break; - case ICMP_REDIRECT: - switch(icp->icmp_code) { - case ICMP_REDIR_NET: - (void)printf("Redirect Network"); - break; - case ICMP_REDIR_HOST: - (void)printf("Redirect Host"); - break; - case ICMP_REDIR_NETTOS: - (void)printf("Redirect Type of Service and Network"); - break; - case ICMP_REDIR_HOSTTOS: - (void)printf("Redirect Type of Service and Host"); - break; - default: - (void)printf("Redirect, Bad Code: %d", icp->icmp_code); - break; - } - (void)printf("(New addr: %s)\n", - inet_ntoa(icp->icmp_gwaddr)); - #ifndef icmp_data - pr_retip((struct iphdr *)(icp + 1)); - #else - pr_retip((struct iphdr *)icp->icmp_data); - #endif - break; - case ICMP_ECHO: - (void)printf("Echo Request\n"); - /* XXX ID + Seq + Data */ - break; - case ICMP_TIME_EXCEEDED: - switch(icp->icmp_code) { - case ICMP_EXC_TTL: - (void)printf("Time to live exceeded\n"); - break; - case ICMP_EXC_FRAGTIME: - (void)printf("Frag reassembly time exceeded\n"); - break; - default: - (void)printf("Time exceeded, Bad Code: %d\n", - icp->icmp_code); - break; - } - #ifndef icmp_data - pr_retip((struct iphdr *)(icp + 1)); - #else - pr_retip((struct iphdr *)icp->icmp_data); - #endif - break; - case ICMP_PARAMETERPROB: - (void)printf("Parameter problem: IP address = %s\n", - inet_ntoa (icp->icmp_gwaddr)); - #ifndef icmp_data - pr_retip((struct iphdr *)(icp + 1)); - #else - pr_retip((struct iphdr *)icp->icmp_data); - #endif - break; - case ICMP_TIMESTAMP: - (void)printf("Timestamp\n"); - /* XXX ID + Seq + 3 timestamps */ - break; - case ICMP_TIMESTAMPREPLY: - (void)printf("Timestamp Reply\n"); - /* XXX ID + Seq + 3 timestamps */ - break; - case ICMP_INFO_REQUEST: - (void)printf("Information Request\n"); - /* XXX ID + Seq */ - break; - case ICMP_INFO_REPLY: - (void)printf("Information Reply\n"); - /* XXX ID + Seq */ - break; - #ifdef ICMP_MASKREQ - case ICMP_MASKREQ: - (void)printf("Address Mask Request\n"); - break; - #endif - #ifdef ICMP_MASKREPLY - case ICMP_MASKREPLY: - (void)printf("Address Mask Reply\n"); - break; - #endif - default: - (void)printf("Bad ICMP type: %d\n", icp->icmp_type); - } - } - - /* - * pr_iph -- - * Print an IP header with options. - */ - static void - pr_iph(struct iphdr *ip) - { - int hlen; - u_char *cp; - - hlen = ip->ip_hl << 2; - cp = (u_char *)ip + 20; /* point to options */ - - (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data\n"); - (void)printf(" %1x %1x %02x %04x %04x", - ip->ip_v, ip->ip_hl, ip->ip_tos, ip->ip_len, ip->ip_id); - (void)printf(" %1x %04x", ((ip->ip_off) & 0xe000) >> 13, - (ip->ip_off) & 0x1fff); - (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p, ip->ip_sum); - (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_src))); - (void)printf(" %s ", inet_ntoa(*((struct in_addr *) &ip->ip_dst))); - /* dump and option bytes */ - while (hlen-- > 20) { - (void)printf("%02x", *cp++); - } - (void)putchar('\n'); - } - - /* - * pr_addr -- - * Return an ascii host address as a dotted quad and optionally with - * a hostname. - */ - static char * - pr_addr(u_long l) - { - struct hostent *hp; - static char buf[256]; - - if ((options & F_NUMERIC) || - !(hp = gethostbyaddr((char *)&l, 4, AF_INET))) - (void)snprintf(buf, sizeof(buf), "%s", - inet_ntoa(*(struct in_addr *)&l)); - else - (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name, - inet_ntoa(*(struct in_addr *)&l)); - return(buf); - } - - /* - * pr_retip -- - * Dump some info on a returned (via ICMP) IP packet. - */ - static void - pr_retip(struct iphdr *ip) - { - int hlen; - u_char *cp; - - pr_iph(ip); - hlen = ip->ip_hl << 2; - cp = (u_char *)ip + hlen; - - if (ip->ip_p == 6) - (void)printf("TCP: from port %u, to port %u (decimal)\n", - (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); - else if (ip->ip_p == 17) - (void)printf("UDP: from port %u, to port %u (decimal)\n", - (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3))); - } - - static void - fill(void *bp1, char *patp) - { - register int ii, jj, kk; - int pat[16]; - char *cp, *bp = (char *)bp1; - - for (cp = patp; *cp; cp++) - if (!isxdigit(*cp)) { - (void)fprintf(stderr, - "ping: patterns must be specified as hex digits.\n"); - exit(2); - } - ii = sscanf(patp, - "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", - &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6], - &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12], - &pat[13], &pat[14], &pat[15]); - - if (ii > 0) - for (kk = 0; kk <= MAXPACKET - (8 + ii); kk += ii) - for (jj = 0; jj < ii; ++jj) - bp[jj + kk] = pat[jj]; - if (!(options & F_QUIET)) { - (void)printf("PATTERN: 0x"); - for (jj = 0; jj < ii; ++jj) - (void)printf("%02x", bp[jj] & 0xFF); - (void)printf("\n"); - } - } - - static void - usage(void) - { - (void)fprintf(stderr, - "usage: ping [-LRdfnqrv] [-c count] [-i wait] [-l preload]\n\t[-p pattern] [-s packetsize] [-t ttl] [-I interface address] host\n"); - exit(2); - } diff --git a/res/moralesty1/pong.cpp b/res/moralesty1/pong.cpp deleted file mode 100644 index 33ef7ee..0000000 --- a/res/moralesty1/pong.cpp +++ /dev/null @@ -1,968 +0,0 @@ -/* - -Pong - -Using the Internet Control Message Protocol (ICMP) ECHO_REQUEST -and ECHO_REPLY messages to measure round-trip-delays and packet -loss across network paths. Eventually, we'd like to expand -this to UDP pinging as well. - -Created as a 2013 NDSU Capstone Project with specifications -and requirements provided by Ericsson. - -An extension/reimplementation of the original ping.c for the 21st -century. -Emphasis is on readability and ease of understanding the code. -Inspiration and design inspired by: - -Mike Muuss -U. S. Army Ballistic Research Laboratory -December, 1983 -Modified at UC Berkeley - -*/ - - -/* - -Imports and definitions - -*/ - -#define IP_MINLENGTH 34 -#define ICMP_MINLENGTH 16 -#define DEFAULT_LISTEN_TIMEOUT 2 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __MACH__ -#include -#include -#endif - -#if __unix__||__APPLE__ -#include -#include -#include -#include -#include -#include -#include -#include - -#elif WIN32 -#include -#include -struct sockaddr_in *socketAddress; -/* ICMP Header for Windows branch */ -struct icmp { - BYTE icmp_type; // ICMP packet type - BYTE icmp_code; // Type sub code - USHORT icmp_cksum; - USHORT icmp_id; - USHORT icmp_seq; - ULONG icmp_data; // not part of ICMP, but we need it -}; -#endif - -/* - -Initialize Structs - -*/ - -struct sockaddr_in *whereto; -struct in_addr destIP; -struct in_addr srcIP; -struct icmp * icmpHeader; -struct icmp * receivedICMPHeader; -struct icmp * receivedIPHeader; -struct ip * ipHeader; -u_char * packet[100]; -u_char * packetIP[100]; - -/* - -Global Variables for stats and keeping track -of how many pings were sent, how many need -to be excluded, and more. - -*/ -int sent; -int packetsTimedOut = 0; -int processID; -int icmpPayloadLength = 30; -int pingsToSend = 5; -int pingsSent = 0; -int pingsToExclude = 0; -double totalResponseTime = 0.0; -double sumOfResponseTimesSquared = 0.0; -double roundTripTime = 0.0; -int pingsReceived = 0; -bool excludingPing; -int timeoutInput = DEFAULT_LISTEN_TIMEOUT; -volatile bool killSwitch = true; - - - - - -/* - -Checksum() - -Simple checksum function for ICMP Header. This implentation was -adapted from Mike Musss' version of ping.c - -*/ -static u_short checksum(u_short *ICMPHeader, int len) -{ - register int nleft = len; - register u_short *ICMPPointer = ICMPHeader; - register int sum = 0; - u_short answer = 0; - - /* - Our algorithm is simple, using a 32 bit accumulator (sum), we add - sequential 16 bit words to it, and at the end, fold back all the - carry bits from the top 16 bits into the lower 16 bits. - */ - while (nleft > 1) - { - sum += *ICMPPointer; - ICMPPointer++; - nleft -= 2; - } - - /* Mop up an odd byte, if necessary */ - if (nleft == 1) - { - *(u_char *)(&answer) = *(u_char *) ICMPPointer; - sum += answer; - } - - /* Add back carry outs from top 16 bits to low 16 bits */ - sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ - sum += (sum >> 16); /* add carry */ - answer = (u_short)~sum; /* truncate to 16 bits */ - return(answer); -} - -/* - -pingICMP() - -This method actually sends our ECHO_REQUEST across the internet. -It computes the ICMP checksum and sends the packet to the address -specified in main(). - -*/ -void pingICMP(int socketDescriptor, int icmpPayloadLength) -{ - /* Get time, put it in the packet */ - - /* Set time sent */ - #ifdef __MACH__ - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, (mach_timespec_t *)icmpHeader->icmp_data); - mach_port_deallocate(mach_task_self(), cclock); - - #elif __WINDOWS__ - // GetTick64Count() - #elif __GNUC__ - clock_gettime(CLOCK_MONOTONIC, (struct timespec *)icmpHeader->icmp_data); - #else - //clock_gettime(CLOCK_REALTIME, &ts); - #endif - - /* Compute checksum */ - icmpHeader->icmp_cksum = 0; - icmpHeader->icmp_cksum = checksum((u_short *)icmpHeader, sizeof(*icmpHeader)); - - /* Try to send the packet */ - sent = sendto(socketDescriptor, packet, icmpPayloadLength + 8, 0, (struct sockaddr *)whereto, sizeof(struct sockaddr)); - - /* Check if the packet sent or not */ - if(sent > 0) - { - pingsSent++; - /* Increment the packet sequence number */ - icmpHeader->icmp_seq++; - } - else - { - printf("Ping not sent.\n\n"); - } -} - -/* - -report() - -This function reports the final statistics, either to the command line -or to a CSV (comma separated value) file. Current statistics and output -information includes pings sent, pings received, pings dropped, pings excluded, -average response time, and standard deviation for response time. - -*/ -void report() -{ - if(pingsSent != 0) - { - printf("----------------------------------------------------------------\n"); - printf("%d packets sent, %d dropped", pingsSent, (pingsSent - pingsReceived)); - if(excludingPing) - { - printf(", %d excluded from summary\n", pingsToExclude); - } - else - { - printf("\n"); - } - double average = totalResponseTime / (pingsSent - pingsToExclude); - printf("Stats avg/stddev : %f / %f\n", average, sqrt((sumOfResponseTimesSquared / (pingsReceived - pingsToExclude)) - (average * average))); - printf("----------------------------------------------------------------\n"); - } -} - -/* - -listenICMP() - -This function waits from an incoming packet, checks to see if it is our ECHO_REPLY, -and then gets data out of the packet and computes statistics or doesn't (depending -on if we're excluding that response or not). - -*/ -void listenICMP(int socketDescriptor, sockaddr_in * fromWhom, bool quiet, bool excludingPings, int timeoutLength) -{ - /* Setting some variables needed for select() and our file descriptor */ - char receivedPacketBuffer[512]; - fd_set readfds; - FD_SET(socketDescriptor, &readfds); - struct timeval timeout; - timeout.tv_sec = timeoutLength; // timeout period, seconds (added second, if that matters) - //printf("Timeout length") - timeout.tv_usec = 0; // timeuot period, microseconds 1,000,000 micro = second - // TODO Make this timeout dependent on how many pings have been sent... - int selectStatus = select(socketDescriptor+1, &readfds, NULL, NULL, &timeout); - socklen_t fromWhomLength = sizeof(fromWhom); - if(selectStatus == -1) - { - printf("LISTEN: Error in select()\n"); - } - else if(selectStatus == 0) - { - printf("I'm tired of waiting. Timeout.\n"); - packetsTimedOut++; - csvOutput << "Dropped" << endl; - return; - } - else - { - if(FD_ISSET(socketDescriptor, &readfds)) - { - - /* Receive the data */ - ssize_t bytesReceived = recvfrom(socketDescriptor, receivedPacketBuffer, sizeof(receivedPacketBuffer), 0, (struct sockaddr *)&fromWhom, &fromWhomLength); - - /* Format the received data into the IP struct, then shift bits */ - struct ip * receivedIPHeader = (struct ip *) receivedPacketBuffer; - int headerLength = receivedIPHeader->ip_hl << 2; - - /* Format the received data into the ICMP struct */ - receivedICMPHeader = (struct icmp *)(receivedPacketBuffer + headerLength); - - /* Get the time */ - #if __MACH__ - clock_get_time(cclock, &receivedTime); - mach_timespec_t * sentTime = (mach_timespec_t *)receivedICMPHeader->icmp_data; - /* Thanks Richard Stevens' book UNIX Network Programming for helping with - this next chunk of time processing code */ - if ( (receivedTime.tv_nsec -= sentTime->tv_nsec) < 0) - { - --receivedTime.tv_sec; - receivedTime.tv_nsec += 1000000000; - } - - #elif __WINDOWS__ - // GetTick64Count() - #elif __GNUC__ - clock_gettime(CLOCK_MONOTONIC, &receivedTime2); - struct timespec * sentTime2 = (struct timespec *)receivedICMPHeader->icmp_data; - /* Thanks Richard Stevens' book UNIX Network Programming for helping with - this next chunk of time processing code */ - if ( (receivedTime2.tv_nsec -= sentTime2->tv_nsec) < 0) - { - --receivedTime2.tv_sec; - receivedTime2.tv_nsec += 1000000000; - } - - #endif - - /* Check if the packet was an ECHO_REPLY, and if it was meant for our computer using the ICMP id, - which we set to the process ID */ - if (receivedICMPHeader->icmp_type == 0) - { - - if(receivedICMPHeader->icmp_id != processID) - { - printf("Not our packet\n"); - printf("processID = %d \t ID = %d\n", processID, receivedICMPHeader->icmp_id); - } - else - { - /* We got a valid reply. Count it! */ - pingsReceived++; - - /* Calculate round trip time */ - if(!excludingPings) - { - #if __MACH__ - receivedTime.tv_sec -= sentTime->tv_sec; - roundTripTime = receivedTime.tv_sec * 1000.0 + receivedTime.tv_nsec / 1000000.0; - #elif __GNUC__ - receivedTime2.tv_sec -= sentTime2->tv_sec; - roundTripTime = receivedTime2.tv_sec * 1000.0 + receivedTime2.tv_nsec / 1000000.0; - #endif - sumOfResponseTimesSquared += roundTripTime * roundTripTime; - totalResponseTime += roundTripTime; - } - - /* Get presentation format of source IP */ - char str[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &(receivedIPHeader->ip_src), str, INET_ADDRSTRLEN); - - /* If we're counting stats for this reply, add data to running stats */ - if(!excludingPings) - { - /* If we're in CSV mode, print info to the file instead of to the terminal */ - if(quiet) - { - printf(".\n"); - csvOutput << (bytesReceived + 14) << "," << str << "," << receivedICMPHeader->icmp_seq << "," << (int)receivedIPHeader->ip_ttl << "," << roundTripTime << endl; - } - /* Otherwise, print received reply information to the terminal */ - else - { - printf("%d bytes from %s packet number:%d ttl:%d time:%f ms\n", (bytesReceived + 14), str, receivedICMPHeader->icmp_seq, (int)receivedIPHeader->ip_ttl, roundTripTime); - } - } - } - } - } - } -} - - -/* - -buildPing() - -buildPing() initializes the ICMP Header and IP Header structs, which -contain essential packet information. The IP address information is -set in main(). - -*/ -void buildPing() -{ - icmpHeader = (struct icmp *) packet; - ipHeader= (struct ip *) packetIP; - icmpHeader->icmp_type = 8; // This shouldn't change - icmpHeader->icmp_code = 0; - icmpHeader->icmp_cksum = 0; - icmpHeader->icmp_seq = 1; - icmpHeader->icmp_id = processID; - ipHeader->ip_p = 1; - ipHeader->ip_ttl = 64; //Recommended value, according to the internet. - ipHeader->ip_hl = 5; -} - - -void interrupt(int signal); -/* - -main() - -Where the magic happens. Command line flags are set, program -control is set. - -*/ -char *argv[2]; -int main(int argc, const char** argv) -{ - signal(SIGINT, interrupt); - #ifdef WIN32 - WSADATA wsaData; - int result=WSAStartup(MAKEWORD(2,0), &wsaData); - if(result != 0) { - printf("WSAStartup failed with error: %d\n", wsaData); - return 1; - #endif - printf("----------------------------------------------------------------\n"); - - int socketDescriptor; - - /* - - Variables for command line flag processing - - */ - const char* destination = argv[1]; - bool timeBetweenReq = 0; // -q // --request-time - float msecsBetweenReq = 1000; - bool timeBetweenRepReq = 0; // -b // --reply-request-time - int msecsBetweenRepReq = 0; - bool datagramSizeSet = 0; // -d // --datagram-size - bool payloadSize = 0; // -p // --payload-size - bool randSizeMinMax = 0; // -l // --random-size-minmax - int bytesSizeMin = 0; - int bytesSizeMax = 0; - bool randSizeAvgStd = 0; // -r // --random-size-avgstd - int bytesSizeAvg = 0; - int bytesSizeStd = 0; - bool randTimeMinMax = 0; // -s // --random-time-minmax - int msecsTimeMin = 0; - int msecsTimeMax = 0; - bool randTimeAvgStd = 0; // -t // --random-time-avgstd - int msecsTimeAvg = 0; - int msecsTimeStd = 0; - bool increasingSize = 0; // -i // --increasing-size - int sizeInitial = 0; // Must be greater than or equal to (IP_MINLENGTH + ICMP_MINLENGTH) - int sizeGrowth = 0; - excludingPing = 0; // -e // --exclud - bool multiplePings = 0; // -n // --ping-count - bool csvMode = 0; // -c // --csv - - if(argc - 1 == 0) - { - printf("USAGE:\nePing [host IP or domain name]\n[-n/--pings-to-send num of pings to send]\n[-e/--exclude num of pings to exclude from stats]\n\nTIME\n[-q/--request-time time between sent pings]\n[-t/--random-time-avgstd set random, normally distributed time between pings - enter average and standard deviation]\n[-z/--timeout manually set timeout for listening method]\n\nSIZE\n[-p/--payload-size ICMP payload size] OR [-d/--datagram-size size of whole packet]\n[-r/--random-size-avgstd set random, normally distributed packet sizes - enter average and standard deviation]\n\nOUTPUT\n[-c/--csv output reply information to a csv file]\n"); - printf("----------------------------------------------------------------\n"); - return(1); - } - else - { - - /* Check if we're root. If not, we can't create the raw socket necessary for ICMP */ - if(getuid()!=0 && geteuid()!=0) - { - printf("UID: %d EUID: %d", getuid(), geteuid()); - printf("\nCan't run. I need root permissions to create raw socket. Sorry.\n"); - printf("----------------------------------------------------------------\n"); - return(1); - } - - /* Create socket descriptor for sending and receiving traffic */ - socketDescriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); - - /* Drop root permissions */ - seteuid(501); - setuid(getuid()); - - } - for(int i = 2; i < argc; i++) { - // argv[0] is the ./a which is input - // argv[1] is the address (IPv4, DNS, IPv6) - if(strcmp(argv[i],"-q") == 0 || strcmp(argv[i],"--request-time") == 0) - { - if(timeBetweenRepReq || randTimeMinMax || randTimeAvgStd) - { - printf("-q flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 1 < argc && atoi(argv[i + 1]) >= 0) - { - timeBetweenReq = true; - msecsBetweenReq = atoi(argv[i + 1]); - printf("Flag -q set! Waiting %f milliseconds between ping requests.\n", msecsBetweenReq); - i++; - } - else - { - printf("-q flag not set, requires parameter.\n"); - } - } - } - else if(strcmp(argv[i],"-b") == 0 || strcmp(argv[i],"--reply-request-time") == 0) - { - if(timeBetweenReq || randTimeMinMax || randTimeAvgStd) - { - printf("-b flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 1 < argc && atoi(argv[i + 1]) >= 0) - { - timeBetweenRepReq = true; - msecsBetweenRepReq = atoi(argv[i + 1]); - printf("Flag -b set! Waiting %d milliseconds between receiving a reply and sending a request\n", msecsBetweenRepReq); - i++; - } - else - { - printf("-b flag not set, requires parameter.\n"); - } - } - } - else if(strcmp(argv[i],"-d") == 0 || strcmp(argv[i],"--datagram-size") == 0) - { - if(payloadSize || randSizeMinMax || randSizeAvgStd) - { - printf("-d flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 1 < argc && atoi(argv[i + 1]) > 0) - { - datagramSizeSet = true; - icmpPayloadLength = atoi(argv[i + 1]) - ICMP_MINLEN - IP_MINLENGTH; - if(icmpPayloadLength < 8) - { - printf("Error: datagram size must be greater than 50 bytes.\n"); - printf("----------------------------------------------------------------\n"); - return(1); - } - printf("Flag -d set! Datagram will be %d bytes large.\n", icmpPayloadLength+IP_MINLENGTH+ICMP_MINLEN); - i++; - } - else - { - printf("-d flag not set, requires parameter.\n"); - } - } - } - else if(strcmp(argv[i],"-p") == 0 || strcmp(argv[i],"--payload-size") == 0) - { - if(datagramSizeSet || randSizeMinMax || randSizeAvgStd) - { - printf("-p flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 1 < argc && atoi(argv[i + 1]) >= 0) - { - payloadSize = true; - icmpPayloadLength = atoi(argv[i + 1]); - if(icmpPayloadLength < 8) - { - printf("Error: Payload size must be 8 bytes or greater.\n"); - printf("----------------------------------------------------------------\n"); - return(1); - } - printf("Flag -p set! Payload size will be %d bytes large.\n", icmpPayloadLength); - i++; - } - else - { - printf("-p flag not set, requires parameter.\n"); - } - } - } - else if(strcmp(argv[i],"-l") == 0 || strcmp(argv[i],"--random-size-minmax") == 0) - { - if(datagramSizeSet || payloadSize || increasingSize || randSizeAvgStd) - { - printf("-l flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 2 < argc && atoi(argv[i + 2]) > 0) - { - randSizeMinMax = true; - if(atoi(argv[i + 1]) > atoi(argv[i + 2])) - { - bytesSizeMin = atoi(argv[i + 2]); - bytesSizeMax = atoi(argv[i + 1]); - } - else - { - bytesSizeMin = atoi(argv[i + 1]); - bytesSizeMax = atoi(argv[i + 2]); - } - printf("Flag -l set! Random size will be between %d ", bytesSizeMin); - printf("and %d.\n", bytesSizeMax); - i += 2; - } - else - { - printf("-l flag not set, requires parameters.\n"); - } - } - } - else if(strcmp(argv[i],"-r") == 0 || strcmp(argv[i],"--random-size-avgstd") == 0) - { - if(datagramSizeSet || payloadSize || increasingSize || randSizeMinMax) - { - printf("-r flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 2 < argc && atoi(argv[i + 2]) > 0) - { - randSizeAvgStd = true; - bytesSizeAvg = atoi(argv[i + 1]); - bytesSizeStd = atoi(argv[i + 2]); - printf("Flag -r set! Random size will average %d",bytesSizeAvg); - printf(" with a std. dev. of %d.\n", bytesSizeStd); - i += 2; - } - else - { - printf("-r flag not set, requires parameters.\n"); - } - } - } - else if(strcmp(argv[i],"-s") == 0 || strcmp(argv[i],"--random-time-minmax") == 0) - { - if(timeBetweenReq || timeBetweenRepReq || randTimeAvgStd) - { - printf("-s flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 2 < argc && atoi(argv[i + 2]) > 0) - { - randTimeMinMax = true; - if(atoi(argv[i + 1]) > atoi(argv[i + 2])) - { - msecsTimeMin = atoi(argv[i + 2]); - msecsTimeMax = atoi(argv[i + 1]); - } - else - { - msecsTimeMin = atoi(argv[i + 1]); - msecsTimeMax = atoi(argv[i + 2]); - } - printf("Flag -s set! Random time between requests will be between %d ", msecsTimeMin); - printf("and %d.\n", msecsTimeMax); - i += 2; - } - else - { - printf("-s flag not set, requires parameters.\n"); - } - } - } - else if(strcmp(argv[i],"-t") == 0 || strcmp(argv[i],"--random-time-avgstd") == 0) - { - if(timeBetweenReq || timeBetweenRepReq || randTimeMinMax) - { - printf("-t flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 2 < argc && atoi(argv[i + 2]) > 0) - { - randTimeAvgStd = true; - msecsTimeAvg = atoi(argv[i + 1]); - msecsTimeStd = atoi(argv[i + 2]); - printf("Flag -t set! Random time between requests will average %d ",msecsTimeAvg); - printf("with a std. dev. of %d.\n", msecsTimeStd); - i += 2; - } - else - { - printf("-t flag not set, requires parameters.\n"); - } - } - } - else if(strcmp(argv[i],"-i") == 0 || strcmp(argv[i],"--increasing-size") == 0) - { - if(datagramSizeSet || payloadSize || randSizeMinMax || randSizeAvgStd) - { - printf("-i flag not set, conflicting with previously set flag.\n"); - } - else - { - if(i + 2 < argc && atoi(argv[i + 2]) > 0) - { - increasingSize = true; - sizeInitial = atoi(argv[i + 1]); - sizeGrowth = atoi(argv[i + 2]); - if(sizeInitial >= (IP_MINLENGTH + ICMP_MINLENGTH)) - { - printf("Flag -i set! Pings will have an initial size of %d ", sizeInitial); - printf("and grow at a rate of %d per request.\n", sizeGrowth); - - //Subtract growth from initial once so when we ping, we can add sizeGrowth to it every time, - //and initialGrowth is still proper - icmpPayloadLength = sizeInitial - sizeGrowth - IP_MINLENGTH - ICMP_MINLENGTH + 8; - } - else - { - printf("Problem: Initial size must be greater than IP header size plus the ICMP header size (%d).\n", IP_MINLENGTH + ICMP_MINLENGTH); - return(1); - } - i += 2; - } - else - { - printf("-i flag not set, requires parameters.\n"); - } - } - } - else if(strcmp(argv[i],"-e") == 0 || strcmp(argv[i],"--exclude") == 0) - { - if(i + 1 < argc && atoi(argv[i + 1]) > 0) - { - excludingPing = true; - pingsToExclude = atoi(argv[i + 1]); - if(pingsToExclude >= pingsToSend) - { - printf("Trying to exclude more pings than you send huh? Not funny.\n"); - exit(0); - } - printf("Flag -e set! %d earliest pings to be excluded from final statistics.\n", pingsToExclude); - i++; - } - else - { - printf("-e flag not set, requires parameter.\n"); - } - - } - else if(strcmp(argv[i],"-n") == 0 || strcmp(argv[i],"--pings-to-send") == 0) - { - if(i + 1 < argc && atoi(argv[i + 1]) > 0) - { - multiplePings = true; - pingsToSend = atoi(argv[i + 1]); - printf("Flag -n set! %d pings to be sent.\n", pingsToSend); - i++; - } - else - { - printf("-n flag not set, requires parameter.\n"); - - } - - } - else if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--csv") == 0) - { - csvMode = 1; - if(i + 1 < argc) - { - csvFileName = argv[i+1]; - i++; - } - else - { - csvFileName = "output.csv"; - } - /* Open the CSV file */ - csvOutput.open(csvFileName); - printf("Flag -c set! Replies will be output to %s.\n", csvFileName.c_str()); - } - else if(strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--timeout") == 0) - { - if(i + 1 < argc && atoi(argv[i + 1]) > 0) - { - timeoutInput = atoi(argv[i + 1]); - i++; - } - - printf("Flag -z set! Listening timeout will be set to %d seconds.\n", timeoutInput); - } - else - { - printf("Flag not recognized, \"%s\"\n",argv[i]); - } - } - printf("Destination set to: %s\n", argv[1]); - - struct addrinfo *result, hints; - hints.ai_family = AF_INET; /* Allow IPv4 or IPv6 */ - hints.ai_socktype = SOCK_RAW; /* RAW socket */ - hints.ai_flags = AI_PASSIVE; /* Fill in my IP address */ - int status; - - /* Convert address */ - if((status = getaddrinfo(destination, NULL, &hints, &result)) != 0) - { - printf("getaddrinfo error: %s\n", gai_strerror(status)); - printf("Double check the address that you want to ping.\n"); - exit(1); - } - - whereto = (struct sockaddr_in *)result->ai_addr; - - - /* - - WINDOWS block for setting the source and destination IP address - - */ - #if WIN32 - sockAddress = &whereto; - int sizeOfAddress=sizeof(IPHeader.destinationIPAddress); - if(WSAStringToAddress((char *)destination,AF_INET,NULL,(LPSOCKADDR)&IPHeader.destinationIPAddress.S_un.S_un_W,&sizeOfAddress)!=0) - { - int error=WSAGetLastError(); - std::cout<sin_addr),(int*)sizeof(socketAddress->sin_addr))!=0) - { - int error=WSAGetLastError(); - std::cout< distribution(bytesSizeAvg, bytesSizeStd); - std::normal_distribution distribution2(msecsTimeAvg, msecsTimeStd); - - - /* Specify that we want two threads (one for listening, one for sending) */ - omp_set_num_threads(2); - - /* - - Execute the ping/listen functions in sequential mode (wait for reply before sending request) - - */ - if(timeBetweenRepReq) - { - while(pingsSent < pingsToSend) - { - - pingICMP(socketDescriptor, icmpPayloadLength); - listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); - usleep(msecsBetweenRepReq * 1000); - } - - } - - /* - - Execute the ping/listen functions in parallel with OpenMP threading - - */ - else - { - - #pragma omp parallel sections - { - - /* Sending block */ - #pragma omp section - for (i = 0; i < pingsToSend; i++) - { - /* Ping */ - if(randSizeAvgStd) - { - randomDatagramSize = distribution(generator); - pingICMP(socketDescriptor, randomDatagramSize - IP_MINLENGTH - ICMP_MINLEN); - } - else if(increasingSize) - { - icmpPayloadLength += sizeGrowth; - pingICMP(socketDescriptor, icmpPayloadLength); - } - else - { - pingICMP(socketDescriptor, icmpPayloadLength); - } - - /* Wait */ - if(randTimeAvgStd) - { - randomTime = distribution2(generator); - usleep(randomTime * 1000); - } - else - { - usleep(msecsBetweenReq * 1000); - } - } - - /* Listening block */ - #pragma omp section - while(i != pingsToSend - 1 && pingsToSend != pingsReceived + packetsTimedOut && killSwitch) - { - - /* If we're excluding some pings, listen but don't print any info */ - if(excludingPing && pingsReceived < pingsToExclude) - { - listenICMP(socketDescriptor, &sourceSocket, 1, 1, timeoutInput); - } - - /* If we're outputting to a CSV file, don't print out so much on the terminal */ - else if(csvMode) - { - listenICMP(socketDescriptor, &sourceSocket, 1, 0, timeoutInput); - } - - /* Otherwise, print all statistics and information to the terminal */ - else - { - listenICMP(socketDescriptor, &sourceSocket, 0, 0, timeoutInput); - } - - } - - } - } - - /* Print final statistics and quit */ - report(); - - if(csvMode) - { - csvOutput.close(); - } - #ifdef WIN32 - int result = WSACleanup(); - #endif - return(0); - } - - void interrupt(int signal) - { - if(killSwitch) - { - pingsToSend = 0; - killSwitch = false; - } - } diff --git a/res/picture.png b/res/picture.png deleted file mode 100644 index 0524a970628c02b90fd22dd6a7b0d83c0bb37d31..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18065 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