| /* |
| # |
| # |
| # Task Subprogram |
| # |
| # SUBPROGRAM NAME: PINGPONG6.C |
| # |
| # REQUIRED PARAMETERS: |
| # Calling Procedure: pingpong6 HOST SIZE PACKETS |
| # HOST - Current host |
| # SIZE - Size of each packet |
| # PACKETS - the number of packets across the network |
| # |
| # SETUP REQUIRED: |
| # o This task must be run as root. |
| # o TCP/IP must be configured before executing this task. |
| # |
| # DESCRIPTION: |
| # Purpose:To generate lan traffic with ICMP6 echo packet |
| # Command: None |
| # Subcommand:None |
| # Design: |
| # Create raw socket |
| # spawn child process to send echo ICMP6 packet |
| # the child process build echo packet and send to network |
| # repeat n times |
| # the parent goes on to receive the reply |
| # when finish print # of packets sent & # pf packets received |
| # |
| # |
| #=========================================================================== |
| */ |
| |
| #define PS2 |
| #include <stdio.h> |
| #include <errno.h> |
| #include <string.h> |
| #include <sys/time.h> |
| #include <sys/types.h> |
| |
| #include <sys/param.h> |
| #include <sys/socket.h> |
| #include <sys/file.h> |
| #include <sys/signal.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| #include <netinet/in_systm.h> |
| #include <netinet/in.h> |
| #include <netinet/ip6.h> |
| #include <netinet/icmp6.h> |
| #include <netdb.h> |
| |
| #define MAXPACKET 4096 /* max packet size */ |
| #ifndef MAXHOSTNAMELEN |
| #define MAXHOSTNAMELEN 64 |
| #endif |
| |
| int pfd[2]; |
| int fdstr[10]; |
| int verbose; |
| int count; |
| u_char packet[MAXPACKET]; |
| int options; |
| int s; /* Socket file descriptor */ |
| struct addrinfo *hp; /* Pointer to host info */ |
| struct addrinfo hints; |
| |
| struct sockaddr_in6 whereto;/* Who to pingpong */ |
| int datalen; /* How much data */ |
| |
| char *hostname; |
| char hnamebuf[MAXHOSTNAMELEN]; |
| |
| int npackets=1; |
| int ntransmitted = 0; /* sequence # for outbound packets = #sent */ |
| int ident; |
| |
| int nreceived = 0; /* # of packets we got back */ |
| int timing = 0; |
| void finish(int); |
| int nwrite; |
| /* |
| * M A I N |
| */ |
| int |
| main(argc, argv) |
| char *argv[]; |
| { |
| struct sockaddr_in6 from; |
| char **av = argv; |
| int nrcv; |
| int on = 1; |
| int rc = 0; |
| struct protoent *proto; |
| int gai; |
| |
| printf ("Starting pingpong - to send / receive packets from host \n"); |
| |
| /* Get Host net address */ |
| printf ("Get host net address for sending packets \n"); |
| memset(&hints, 0, sizeof(hints)); |
| hints.ai_family = PF_INET6; |
| |
| if ((gai=getaddrinfo(av[1], NULL, &hints, &hp))!=0) { |
| fprintf(stderr, "Unknown subject address %s: %s\n",av[1], gai_strerror(gai)); |
| exit(1); |
| } |
| if (!hp->ai_addr || hp->ai_addr->sa_family != AF_INET6) { |
| fprintf(stderr, "getaddrinfo failed"); |
| exit(1); |
| } |
| strcpy(hnamebuf, av[1]); |
| hostname = hnamebuf; |
| memset( (char *)&whereto, 0x00, sizeof(struct sockaddr) ); |
| memcpy(&whereto, hp->ai_addr, hp->ai_addrlen); |
| |
| /* Determine Packet Size - either use what was passed in or default */ |
| printf ("Determine packet size \n"); |
| if (argc >= 3) |
| datalen = atoi( av[2] ) - 8; |
| else |
| datalen = 64-8; |
| if (datalen > MAXPACKET) { |
| printf("Pingpong: packet size too large\n"); |
| exit(1); |
| } |
| |
| /* Set number of packets to be sent */ |
| printf ("Determine number of packets to send \n"); |
| if (argc >= 4) |
| npackets = atoi(av[3]); |
| |
| /* Get PID of current process */ |
| ident = getpid() & 0xFFFF; |
| |
| /* Get network protocol to use (check /etc/protocol) */ |
| if ((proto = getprotobyname("ipv6-icmp")) == NULL) { |
| printf("ICMP6: unknown protocol\n"); |
| exit(1); |
| } |
| |
| /* Create a socket endpoint for communications - returns a descriptor */ |
| if ((s = socket(AF_INET6, SOCK_RAW, proto->p_proto)) < 0) { |
| printf("Pingpong: socket - could not create link \n"); |
| exit(1); |
| } |
| |
| printf("echoing %s: %d data bytes\n", hostname, datalen ); |
| printf("Total packet size is %d bytes\n",datalen+8); |
| |
| setlinebuf( stdout ); |
| |
| /* Setup traps */ |
| signal( SIGINT, finish ); |
| signal( SIGCLD, finish ); |
| |
| /* Fork a child process to continue sending packets */ |
| printf ("Create a child process to continue to send packets \n"); |
| switch (fork()) { |
| case -1: |
| printf("ERROR when forking a new process\n"); |
| exit(1); |
| case 0: |
| /* Child's work */ |
| ntransmitted=echopkt(datalen,npackets); |
| printf("%d packets transmitted, ",ntransmitted); |
| sleep(10); |
| break; |
| default: |
| printf ("Parent started - to receive packets \n"); |
| /* Parent's work - receive packets back from child */ |
| for (;;) { |
| int len = sizeof (packet); |
| unsigned int fromlen = sizeof (from); |
| #ifdef __64BIT__ |
| long cc; |
| #else |
| int cc; |
| #endif |
| |
| /* Receive packet from socket */ |
| fromlen = sizeof (from); |
| if ((cc=recvfrom(s, packet, len, 0, (struct sockaddr *)&from, &fromlen)) < 0) { |
| printf("ERROR in recvfrom\n"); |
| } |
| /* Verify contents of packet */ |
| if ((rc = ck_packet (packet, cc, &from)) == 0) |
| nreceived++; |
| } |
| } |
| return 0; |
| } |
| |
| echopkt(datalen,npackets) |
| int datalen; |
| int npackets; |
| { |
| int count=0; |
| static u_char outpack[MAXPACKET]; |
| register struct icmp6_hdr *icp = (struct icmp6_hdr *) outpack; |
| int i; |
| #ifdef __64BIT__ |
| long cc; |
| #else |
| int cc; |
| #endif |
| |
| register u_char *datap = &outpack[8]; |
| |
| /* Setup the packet structure */ |
| printf ("Setup ICMP packet structure to send to host \n"); |
| icp->icmp6_type = ICMP6_ECHO_REQUEST; |
| icp->icmp6_code = 0; |
| icp->icmp6_cksum = 0; |
| icp->icmp6_id = ident; /* ID */ |
| |
| cc = datalen+8; /* skips ICMP portion */ |
| |
| for (i=0; i<datalen; i++) { |
| *datap++ = 6; |
| } |
| ntransmitted=0; |
| while (count < npackets) { |
| count++; |
| /* Send packet through socket created */ |
| printf ("Sending packet through created socket \n"); |
| i = sendto( s, outpack, cc, 0, &whereto, sizeof(whereto) ); |
| |
| if (i < 0 || i != cc) { |
| if (i < 0) perror("sendto"); |
| printf("pingpong6: wrote %s %d chars, ret=%d\n",hostname,cc,i); |
| fflush(stdout); |
| } |
| } |
| /* sleep(30); */ |
| return(count); |
| } |
| |
| /* |
| * F I N I S H |
| * |
| * Outputs packet information to confirm transmission and reception. |
| */ |
| void finish(int n) |
| { |
| printf("%d packets received, \n", nreceived ); |
| exit(0); |
| } |
| |
| /* |
| * C K _ P A C K E T |
| * |
| * Checks contents of packet to verify information did not get destroyed |
| */ |
| |
| ck_packet (buf, cc, from) |
| u_char *buf; /* pointer to start of IP header */ |
| int cc; /* total size of received packet */ |
| struct sockaddr_in6 *from; /* address of sender */ |
| { |
| int i; |
| struct icmp6_hdr icp_hdr; |
| struct icmp6_hdr *icp = (struct ip6_hdr *) buf; /* pointer to IP header */ |
| u_char *datap ; |
| |
| datap = (u_char *)icp + sizeof(icp_hdr); |
| if (icp->icmp6_type != ICMP6_ECHO_REPLY) { |
| return(1); /* Not your packet 'cause not an echo */ |
| } |
| if (icp->icmp6_id != ident) { |
| return(1); /* Sent to us by someone else */ |
| } |
| printf("Receiving packet \n"); |
| /* Verify data in packet */ |
| |
| printf ("Checking Data.\n"); |
| for (i=0; i<datalen; i++) { |
| if ((*datap) != 6) { |
| printf ("RVW: Data in [%d] is %d\n",i,(*datap)); |
| printf ("Data cannot be validated. \n"); |
| } |
| datap++; |
| } |
| return(0); |
| } |