home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume8 / bug / bug.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-10-01  |  5.5 KB  |  219 lines

  1. /* Copyright (C) 1989 by Matthew Merzbacher.
  2.    All Rights Reserved.
  3.    Bug is provided as is, without express or implied warranty.  In no event
  4.    shall Matthew Merzbacher become liable for any loss or damages, consequential
  5.    or otherwise, arising from the use or possession of this software.
  6. */
  7.  
  8. #include <sys/types.h>
  9. #include <sys/socket.h>
  10. #include <netinet/in.h>
  11. #include <netdb.h>
  12. #include <stdio.h>
  13. #include <fcntl.h>
  14.  
  15. #define MARK "<MARK>"
  16. #define MARKLEN 6
  17.  
  18. /*
  19.  * Brief Description:
  20.  * Bug is used to tap a stream socket.  It is useful for tracing communication 
  21.  * between a server and its clients.  The communication between server and
  22.  * client is maintained while transcripts of all communication lines are taken.
  23.  * It has six required (and no optional) arguments.  
  24.  *
  25.  * Usage:
  26.  * bug <in port> <out port> <machine> <client file> <server file>
  27.  *
  28.  * <in port>     - the port (on the machine on which bug runs) to which to
  29.  *                   clients will connect (the pseudo-port)
  30.  * <out port>    - the true server port
  31.  * <machine>     - the server machine
  32.  * <client file> - transcript file of what each client says
  33.  * <server file> - transcript file of what the server responds
  34.  *
  35.  * Example: 
  36.  * Suppose a server listens on port 3000 of machine "xyz".  The user must 
  37.  * artificially make the clients talk to some other port (on any machine -
  38.  * it could be the server machine, the client machine, or a third machine).
  39.  * That port is called the pseudo-port.  Bug runs on the machine of the
  40.  * pseudo-port.  To run it, type:
  41.  * 
  42.  * bug 2999 3000 xyz client server
  43.  *
  44.  * This assumes that the pseudo-port is 2999.  The output files will all start
  45.  * with "client" or "server" followed by the process number of the bug process
  46.  * and the process number of each seperate listening session.  That way, you
  47.  * can follow the connection order.  Typically, the output files created by bug
  48.  * may be read by using 'od -c'.
  49.  *
  50.  */
  51.  
  52. main(argc, argv)
  53. int argc; char *argv[];
  54. {
  55.     struct sockaddr_in server;
  56.     struct hostent *hp, *gethostbyname();
  57.     char buf[1024];
  58.     int rval;
  59.     int outfile1, outfile2;
  60.     int insock, outsock, msgsock;
  61.     int insocknum, outsocknum;
  62.     fd_set fdset;
  63.  
  64.  
  65.     /* Check Arguments */
  66.  
  67.     if (argc < 6) {
  68.     printf("usage: %s <in port> <out port> <machine> <client file> <server file>\n",argv[0]);
  69.     exit(1);
  70.     }
  71.  
  72.     insocknum = atoi(argv[1]);
  73.     outsocknum = atoi(argv[2]);
  74.  
  75.  
  76.     /* Create listening post on pseudo-port */
  77.  
  78.     insock = socket(AF_INET, SOCK_STREAM, 0);
  79.  
  80.     if (insock < 0) {
  81.     perror("opening pseudo-port stream socket");
  82.     exit(1);
  83.     }
  84.  
  85.  
  86.     /* Name socket using user supplied port number */
  87.  
  88.     server.sin_family = AF_INET;
  89.     server.sin_addr.s_addr = INADDR_ANY;
  90.     server.sin_port = insocknum;
  91.  
  92.     if (bind(insock, &server, sizeof(server))) {
  93.     perror("binding pseudo-port stream socket");
  94.     exit(1);
  95.     }
  96.  
  97.  
  98.     /* Start accepting connections */
  99.  
  100.     listen(insock, SOMAXCONN);
  101.  
  102.  
  103.     /* Every connection spawns a child to handle the communication */
  104.  
  105.     do {
  106.     msgsock = accept(insock, 0, 0);
  107.     if (msgsock == -1)
  108.         perror("accept");
  109.     } while (fork() != 0);
  110.  
  111.  
  112.     /* Close listening post - it's now called "msgsock" */
  113.  
  114.     close(insock);
  115.  
  116.  
  117.     /* Create output socket to server */
  118.  
  119.     outsock = socket(AF_INET, SOCK_STREAM, 0);
  120.     if (outsock < 0) {
  121.     perror("opening server stream socket");
  122.     exit(1);
  123.     }
  124.  
  125.  
  126.     /* Connect socket using machine & port specified on command line. */
  127.  
  128.     server.sin_family = AF_INET;
  129.     hp = gethostbyname(argv[3]);
  130.     if (hp == 0) {
  131.     fprintf(stderr, "%s: unknown machine\n", argv[3]);
  132.     exit(2);
  133.     }
  134.  
  135.     bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
  136.     server.sin_port = htons(outsocknum);
  137.  
  138.     if (connect(outsock, &server, sizeof(server)) < 0) {
  139.     perror("connecting server stream socket");
  140.     exit(1);
  141.     }
  142.  
  143.  
  144.     /* Open the output files */
  145.  
  146.     sprintf(buf,"%s.%d.%d",argv[4],getppid(),getpid());
  147.     if ((outfile1 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
  148.     fprintf(stderr,"cannot open file: %s\n",buf);
  149.     exit(1);
  150.     }
  151.  
  152.     sprintf(buf,"%s.%d.%d",argv[5],getppid(),getpid());
  153.     if ((outfile2 = open(buf, O_TRUNC|O_WRONLY|O_CREAT, 0644)) == -1) {
  154.     fprintf(stderr,"cannot open file: %s\n",buf);
  155.     exit(1);
  156.     }
  157.  
  158.     do {
  159.     
  160.     /* find out who's talking */
  161.  
  162.     FD_ZERO(&fdset);
  163.     FD_SET(msgsock, &fdset);
  164.     FD_SET(outsock, &fdset);
  165.     if (select(getdtablesize(), &fdset, 0, 0, 0) == -1) {
  166.         perror("select");
  167.         exit(1);
  168.         }
  169.     bzero(buf, 1024);
  170.  
  171.     if (FD_ISSET(msgsock, &fdset) && FD_ISSET(outsock, &fdset))
  172.         fprintf(stderr,"Two talkers - no listeners\n");
  173.  
  174.  
  175.     /* Client is talking to server */
  176.  
  177.     if (FD_ISSET(msgsock, &fdset)) { 
  178.         if ((rval = read(msgsock, buf, 1024)) < 0)
  179.         perror("reading stream message");
  180.         if (rval == 0)
  181.         fprintf(stderr,"Ending client connection\n");
  182.         else {
  183.         write(outfile1, buf, rval);
  184.         write(outfile1, MARK, 6);
  185.         if (write(outsock, buf, rval) < 0)
  186.             perror("writing on output stream socket");
  187.         }
  188.         }
  189.  
  190.     /* Server is talking to client */
  191.  
  192.     else {
  193.         if (! FD_ISSET(outsock, &fdset)) {
  194.         perror("weird behavior");
  195.         exit(1);
  196.         }
  197.         if ((rval = read(outsock, buf, 1024)) < 0)
  198.         perror("reading stream message");
  199.         if (rval == 0)
  200.         fprintf(stderr,"Ending server connection\n");
  201.         else {
  202.         write(outfile2, buf, rval);
  203.         write(outfile2, MARK, 6);
  204.         if (write(msgsock, buf, rval) < 0)
  205.             perror("writing on output stream socket");
  206.         }
  207.         }
  208.     } while (rval != 0);
  209.  
  210.  
  211.     /* Close up shop */
  212.  
  213.     fprintf(stderr, "Closing Connections\n");
  214.     close(msgsock);
  215.     close(outsock);
  216.     close(outfile1);
  217.     close(outfile2);
  218.     }
  219.