robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 1 | /* |
| 2 | # |
| 3 | # |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 4 | # Task Subprogram |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 5 | # |
| 6 | # SUBPROGRAM NAME: PINGPONG6.C |
| 7 | # |
| 8 | # REQUIRED PARAMETERS: |
| 9 | # Calling Procedure: pingpong6 HOST SIZE PACKETS |
| 10 | # HOST - Current host |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 11 | # SIZE - Size of each packet |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 12 | # PACKETS - the number of packets across the network |
| 13 | # |
| 14 | # SETUP REQUIRED: |
| 15 | # o This task must be run as root. |
| 16 | # o TCP/IP must be configured before executing this task. |
| 17 | # |
| 18 | # DESCRIPTION: |
| 19 | # Purpose:To generate lan traffic with ICMP6 echo packet |
| 20 | # Command: None |
| 21 | # Subcommand:None |
| 22 | # Design: |
| 23 | # Create raw socket |
| 24 | # spawn child process to send echo ICMP6 packet |
| 25 | # the child process build echo packet and send to network |
| 26 | # repeat n times |
| 27 | # the parent goes on to receive the reply |
| 28 | # when finish print # of packets sent & # pf packets received |
| 29 | # |
| 30 | # |
| 31 | #=========================================================================== |
| 32 | */ |
| 33 | |
| 34 | #define PS2 |
| 35 | #include <stdio.h> |
| 36 | #include <errno.h> |
vapier | 32cc0ac | 2006-06-22 04:28:32 +0000 | [diff] [blame] | 37 | #include <string.h> |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 38 | #include <sys/time.h> |
| 39 | #include <sys/types.h> |
| 40 | |
| 41 | #include <sys/param.h> |
| 42 | #include <sys/socket.h> |
| 43 | #include <sys/file.h> |
| 44 | #include <sys/signal.h> |
yaberauneya | 106e74f | 2009-10-17 06:56:58 +0000 | [diff] [blame] | 45 | #include <stdlib.h> |
yaberauneya | 03ce934 | 2009-10-10 23:30:05 +0000 | [diff] [blame] | 46 | #include <unistd.h> |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 47 | |
| 48 | #include <netinet/in_systm.h> |
| 49 | #include <netinet/in.h> |
| 50 | #include <netinet/ip6.h> |
| 51 | #include <netinet/icmp6.h> |
| 52 | #include <netdb.h> |
| 53 | |
| 54 | #define MAXPACKET 4096 /* max packet size */ |
| 55 | #ifndef MAXHOSTNAMELEN |
| 56 | #define MAXHOSTNAMELEN 64 |
| 57 | #endif |
| 58 | |
| 59 | int pfd[2]; |
| 60 | int fdstr[10]; |
| 61 | int verbose; |
| 62 | int count; |
| 63 | u_char packet[MAXPACKET]; |
| 64 | int options; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 65 | int s; /* Socket file descriptor */ |
| 66 | struct addrinfo *hp; /* Pointer to host info */ |
| 67 | struct addrinfo hints; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 68 | |
| 69 | struct sockaddr_in6 whereto;/* Who to pingpong */ |
| 70 | int datalen; /* How much data */ |
| 71 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 72 | char *hostname; |
| 73 | char hnamebuf[MAXHOSTNAMELEN]; |
| 74 | |
| 75 | int npackets=1; |
| 76 | int ntransmitted = 0; /* sequence # for outbound packets = #sent */ |
| 77 | int ident; |
| 78 | |
| 79 | int nreceived = 0; /* # of packets we got back */ |
| 80 | int timing = 0; |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 81 | void finish(int); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 82 | int nwrite; |
| 83 | /* |
| 84 | * M A I N |
| 85 | */ |
yaberauneya | 106e74f | 2009-10-17 06:56:58 +0000 | [diff] [blame] | 86 | int |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 87 | main(argc, argv) |
| 88 | char *argv[]; |
| 89 | { |
| 90 | struct sockaddr_in6 from; |
| 91 | char **av = argv; |
| 92 | int nrcv; |
| 93 | int on = 1; |
| 94 | int rc = 0; |
| 95 | struct protoent *proto; |
| 96 | int gai; |
| 97 | |
| 98 | printf ("Starting pingpong - to send / receive packets from host \n"); |
| 99 | |
| 100 | /* Get Host net address */ |
| 101 | printf ("Get host net address for sending packets \n"); |
| 102 | memset(&hints, 0, sizeof(hints)); |
| 103 | hints.ai_family = PF_INET6; |
| 104 | |
subrata_modak | a2f85d3 | 2008-10-29 05:09:47 +0000 | [diff] [blame] | 105 | if ((gai=getaddrinfo(av[1], NULL, &hints, &hp))!=0) { |
robbiew | dd2c02a | 2002-09-05 15:48:16 +0000 | [diff] [blame] | 106 | fprintf(stderr, "Unknown subject address %s: %s\n",av[1], gai_strerror(gai)); |
subrata_modak | a2f85d3 | 2008-10-29 05:09:47 +0000 | [diff] [blame] | 107 | exit(1); |
| 108 | } |
| 109 | if (!hp->ai_addr || hp->ai_addr->sa_family != AF_INET6) { |
robbiew | dd2c02a | 2002-09-05 15:48:16 +0000 | [diff] [blame] | 110 | fprintf(stderr, "getaddrinfo failed"); |
subrata_modak | a2f85d3 | 2008-10-29 05:09:47 +0000 | [diff] [blame] | 111 | exit(1); |
| 112 | } |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 113 | strcpy(hnamebuf, av[1]); |
| 114 | hostname = hnamebuf; |
vapier | 32cc0ac | 2006-06-22 04:28:32 +0000 | [diff] [blame] | 115 | memset( (char *)&whereto, 0x00, sizeof(struct sockaddr) ); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 116 | memcpy(&whereto, hp->ai_addr, hp->ai_addrlen); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 117 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 118 | /* Determine Packet Size - either use what was passed in or default */ |
| 119 | printf ("Determine packet size \n"); |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 120 | if (argc >= 3) |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 121 | datalen = atoi( av[2] ) - 8; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 122 | else |
| 123 | datalen = 64-8; |
| 124 | if (datalen > MAXPACKET) { |
| 125 | printf("Pingpong: packet size too large\n"); |
| 126 | exit(1); |
| 127 | } |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 128 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 129 | /* Set number of packets to be sent */ |
| 130 | printf ("Determine number of packets to send \n"); |
| 131 | if (argc >= 4) |
| 132 | npackets = atoi(av[3]); |
| 133 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 134 | /* Get PID of current process */ |
| 135 | ident = getpid() & 0xFFFF; |
| 136 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 137 | /* Get network protocol to use (check /etc/protocol) */ |
| 138 | if ((proto = getprotobyname("ipv6-icmp")) == NULL) { |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 139 | printf("ICMP6: unknown protocol\n"); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 140 | exit(1); |
| 141 | } |
| 142 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 143 | /* Create a socket endpoint for communications - returns a descriptor */ |
| 144 | if ((s = socket(AF_INET6, SOCK_RAW, proto->p_proto)) < 0) { |
| 145 | printf("Pingpong: socket - could not create link \n"); |
| 146 | exit(1); |
| 147 | } |
| 148 | |
| 149 | printf("echoing %s: %d data bytes\n", hostname, datalen ); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 150 | printf("Total packet size is %d bytes\n",datalen+8); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 151 | |
| 152 | setlinebuf( stdout ); |
| 153 | |
| 154 | /* Setup traps */ |
| 155 | signal( SIGINT, finish ); |
| 156 | signal( SIGCLD, finish ); |
| 157 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 158 | /* Fork a child process to continue sending packets */ |
| 159 | printf ("Create a child process to continue to send packets \n"); |
| 160 | switch (fork()) { |
| 161 | case -1: |
| 162 | printf("ERROR when forking a new process\n"); |
| 163 | exit(1); |
| 164 | case 0: |
| 165 | /* Child's work */ |
| 166 | ntransmitted=echopkt(datalen,npackets); |
| 167 | printf("%d packets transmitted, ",ntransmitted); |
| 168 | sleep(10); |
| 169 | break; |
| 170 | default: |
| 171 | printf ("Parent started - to receive packets \n"); |
| 172 | /* Parent's work - receive packets back from child */ |
| 173 | for (;;) { |
| 174 | int len = sizeof (packet); |
| 175 | unsigned int fromlen = sizeof (from); |
| 176 | #ifdef __64BIT__ |
| 177 | long cc; |
| 178 | #else |
| 179 | int cc; |
| 180 | #endif |
| 181 | |
| 182 | /* Receive packet from socket */ |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 183 | fromlen = sizeof (from); |
Garrett Cooper | df3eb16 | 2010-11-28 22:44:32 -0800 | [diff] [blame] | 184 | if ((cc=recvfrom(s, packet, len, 0, (struct sockaddr *)&from, &fromlen)) < 0) { |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 185 | printf("ERROR in recvfrom\n"); |
| 186 | } |
| 187 | /* Verify contents of packet */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 188 | if ((rc = ck_packet (packet, cc, &from)) == 0) |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 189 | nreceived++; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 190 | } |
| 191 | } |
Garrett Cooper | 794c1c1 | 2010-12-18 10:36:21 -0800 | [diff] [blame] | 192 | return 0; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | echopkt(datalen,npackets) |
| 196 | int datalen; |
| 197 | int npackets; |
| 198 | { |
| 199 | int count=0; |
| 200 | static u_char outpack[MAXPACKET]; |
| 201 | register struct icmp6_hdr *icp = (struct icmp6_hdr *) outpack; |
| 202 | int i; |
| 203 | #ifdef __64BIT__ |
| 204 | long cc; |
| 205 | #else |
| 206 | int cc; |
| 207 | #endif |
| 208 | |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 209 | register u_char *datap = &outpack[8]; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 210 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 211 | /* Setup the packet structure */ |
| 212 | printf ("Setup ICMP packet structure to send to host \n"); |
| 213 | icp->icmp6_type = ICMP6_ECHO_REQUEST; |
| 214 | icp->icmp6_code = 0; |
| 215 | icp->icmp6_cksum = 0; |
| 216 | icp->icmp6_id = ident; /* ID */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 217 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 218 | cc = datalen+8; /* skips ICMP portion */ |
| 219 | |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 220 | for (i=0; i<datalen; i++) { |
robbiew | ff44419 | 2002-03-01 21:35:17 +0000 | [diff] [blame] | 221 | *datap++ = 6; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 222 | } |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 223 | ntransmitted=0; |
| 224 | while (count < npackets) { |
| 225 | count++; |
| 226 | /* Send packet through socket created */ |
| 227 | printf ("Sending packet through created socket \n"); |
| 228 | i = sendto( s, outpack, cc, 0, &whereto, sizeof(whereto) ); |
| 229 | |
Garrett Cooper | 8fb1cdb | 2010-11-28 22:56:35 -0800 | [diff] [blame] | 230 | if (i < 0 || i != cc) { |
Garrett Cooper | 5374050 | 2010-12-16 00:04:01 -0800 | [diff] [blame] | 231 | if (i < 0) perror("sendto"); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 232 | printf("pingpong6: wrote %s %d chars, ret=%d\n",hostname,cc,i); |
| 233 | fflush(stdout); |
| 234 | } |
| 235 | } |
| 236 | /* sleep(30); */ |
| 237 | return(count); |
| 238 | } |
| 239 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 240 | /* |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 241 | * F I N I S H |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 242 | * |
| 243 | * Outputs packet information to confirm transmission and reception. |
| 244 | */ |
| 245 | void finish(int n) |
| 246 | { |
| 247 | printf("%d packets received, \n", nreceived ); |
| 248 | exit(0); |
| 249 | } |
| 250 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 251 | /* |
| 252 | * C K _ P A C K E T |
| 253 | * |
| 254 | * Checks contents of packet to verify information did not get destroyed |
| 255 | */ |
| 256 | |
| 257 | ck_packet (buf, cc, from) |
robbiew | ff44419 | 2002-03-01 21:35:17 +0000 | [diff] [blame] | 258 | u_char *buf; /* pointer to start of IP header */ |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 259 | int cc; /* total size of received packet */ |
| 260 | struct sockaddr_in6 *from; /* address of sender */ |
| 261 | { |
robbiew | ff44419 | 2002-03-01 21:35:17 +0000 | [diff] [blame] | 262 | int i; |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 263 | struct icmp6_hdr icp_hdr; |
| 264 | struct icmp6_hdr *icp = (struct ip6_hdr *) buf; /* pointer to IP header */ |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 265 | u_char *datap ; |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 266 | |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 267 | datap = (u_char *)icp + sizeof(icp_hdr); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 268 | if (icp->icmp6_type != ICMP6_ECHO_REPLY) { |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 269 | return(1); /* Not your packet 'cause not an echo */ |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 270 | } |
| 271 | if (icp->icmp6_id != ident) { |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 272 | return(1); /* Sent to us by someone else */ |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 273 | } |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 274 | printf("Receiving packet \n"); |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 275 | /* Verify data in packet */ |
robbiew | 590cdde | 2002-02-26 19:16:11 +0000 | [diff] [blame] | 276 | |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 277 | printf ("Checking Data.\n"); |
Garrett Cooper | 2c28215 | 2010-12-16 00:55:50 -0800 | [diff] [blame] | 278 | for (i=0; i<datalen; i++) { |
| 279 | if ((*datap) != 6) { |
robbiew | ff44419 | 2002-03-01 21:35:17 +0000 | [diff] [blame] | 280 | printf ("RVW: Data in [%d] is %d\n",i,(*datap)); |
| 281 | printf ("Data cannot be validated. \n"); |
| 282 | } |
| 283 | datap++; |
| 284 | } |
robbiew | edaaedb | 2002-01-16 21:31:11 +0000 | [diff] [blame] | 285 | return(0); |
Chris Dearman | ec6edca | 2012-10-17 19:54:01 -0700 | [diff] [blame] | 286 | } |