/*                       S E R V . U D P * * This is an example program that demonstrates the use of * datagram sockets as an BSD Sockets mechanism.  This contains * the server, and is intended to operate in conjunction with the * client program found in client.udp. Together, these two * programs demonstrate many of the features of sockets, as well * a good conventions for using these features. NOTE: This example * is valid only if the /etc/hosts file is being used to lookup * host names. * * This program provides a service called "example".  It is an * example of a simple name server.  In order for * it to function, an entry for it needs to exist in the * /etc/services file.  The port address for this service can be * any port number that is likely to be unused, such as 22375, * for example.  The host on which the client will be running * must also have the same entry (same port number) in its * /etc/services file. * */   #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <stdio.h> #include <netdb.h>   int s;                    /* socket descriptor */   #define BUFFERSIZE  1024  /* max size of packets to be received */ int cc;                   /* contains the number of bytes read */ char buffer[BUFFERSIZE];  /* buffer for packets to be read into */   struct hostent *hp;       /* pointer to info of requested host */ struct servent *sp;       /* pointer to service information */   struct sockaddr_in myaddr_in;    /* for local socket address */ struct sockaddr_in clientaddr_in;/* for client's socket address */ struct in_addr reqaddr;         /* for requested host's address */   #define ADDRNOTFOUND 0xffffffff /* return address for unfound host */   /*  *                      M A I N  *  * This routine starts the server.  It forks, leaving the child  * to do all the work, so it does not have to be run in the  * background.  It sets up the socket, and for each incoming  * request, it returns an answer.  Each request consists of a  * host name for which the requester desires to know the  * internet address.  The server will look up the name in its  * /etc/hosts file, and return the internet address to the  * client. An internet address value of all ones will be returned  * if the host name is not found. NOTE: This example is valid  * only if the /etc/hosts file is being used to lookup host names.  *  */ main(argc, argv) int argc; char *argv[]; {         int addrlen;                   /* clear out address structures */    memset ((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));    memset ((char *)&clientaddr_in, 0, sizeof(struct sockaddr_in));                   /* Set up address structure for the socket. */    myaddr_in.sin_family = AF_INET;                 /* The server should receive on the wildcard address,                  * rather than its own internet address.  This is                  * generally good practice for servers, because on                  * systems which are connected to more than one                  * network at once will be able to have one server                  * listening on all networks at once.  Even when the                  * host is connected to only one network, this is good                  * practice, because it makes the server program more                  * portable.                  */   myaddr_in.sin_addr.s_addr = INADDR_ANY;                 /* Find the information for the "example" server                  * in order to get the needed port number.                  */   sp = getservbyname ("example", "udp");   if (sp == NULL) {                 printf("%s: host not found",                                 argv[0]);                 exit(1);   }   myaddr_in.sin_port = sp->s_port;                   /* Create the socket. */   s = socket (AF_INET, SOCK_DGRAM, 0);   if (s == -1) {                 perror(argv[0]);                 printf("%s: unable to create socket\n", argv[0]);                 exit(1);   }             /* Bind the server's address to the socket. */   if (bind(s, &myaddr_in, sizeof(struct sockaddr_in)) == -1) {                 perror(argv[0]);                 printf("%s: unable to bind address\n", argv[0]);                 exit(1);   }              /* Now, all the initialization of the server is             * complete, and any user errors will have already             * been detected.  Now we can fork the daemon and             * return to the user.  We need to do a setpgrp             * so that the daemon will no longer be associated             * with the user's control terminal.  This is done             * before the fork, so that the child will not be             * a process group leader.  Otherwise, if the child             * were to open a terminal, it would become associated             * with that terminal as its control terminal.  It is             * always best for the parent to do the setpgrp.             */   setpgrp();     switch (fork()) {   case -1: /* Unable to fork, for some reason. */            perror(argv[0]);            printf("%s: unable to fork daemon\n", argv[0]);            exit(1);     case 0:  /* The child process (daemon) comes here. */            /* Close stdin, stdout, and stderr so they will             * not be kept open.  From now on, the daemon will             * not report any error messages.  This daemon             * will loop forever, waiting for requests and             * responding to them.             */         fclose(stdin);         fclose(stdout);         fclose(stderr);                /* This will open the /etc/hosts file and keep                 * it open.  This will make accesses to it faster.                 * If the host has been configured to use the NIS                 * server or name server (BIND), it is desirable                  * not to call sethostent(1), because a STREAM                  * socket is used instead of datagrams for each                 * call to gethostbyname().                      */         sethostent(1);         for(;;) {                       /* Note that addrlen passed as a pointer                        * so that the recvfrom call can return                        * the size of the returned address.                        */                 addrlen = sizeof(struct sockaddr_in);                         /* This call will block until a new                        * request arrives.  Then, it will                        * return the address of the client,                        * and a buffer containing its request.                        * BUFFERSIZE - 1 bytes are read so that                        * room is left at the end of the buffer                        * for a null character.                        */                 cc = recvfrom(s, buffer, BUFFERSIZE - 1, 0,                                     &clientaddr_in, &addrlen);                 if ( cc == -1) exit(1);                              /* Make sure the message received is                               * null terminated.                               */                 buffer[cc]='\0';                               /* Treat the message as a string                                * containing a hostname.  Search                                * fot the name in /etc/hosts.                                */                 hp = gethostbyname (buffer);                 if (hp == NULL) {                                     /* Name was not found. Return                                      * a special value signifying                                      * the error.                                      */                           reqaddr.s_addr = ADDRNOTFOUND;                 } else {                                         /* Copy address of host                                         * into the return buffer.                                         */                           reqaddr.s_addr =                         ((struct in_addr *)(hp->h_addr))->s_addr;                 }                              /* Send the response back to the                               * requesting client. The address is                               * sent in network byte order. All                               * errors are ignored. The client                               * will retry if it does not receive                               * the response.                               */                      sendto (s, &reqaddr, sizeof(struct in_addr),                                      0, &clientaddr_in, addrlen);                 }           default:             /* Parent process comes here. */                 exit(0);         } }    /*  *                      C L I E N T . U D P  *  * This is an example program that demonstrates the use of  * datagram sockets as an BSD Sockets mechanism. This contains  * the client, and is intended to operate in conjunction with the  * server program found in serv.udp. Together, these two programs  * demonstrate many of the features of sockets, as well as good  * conventions for using these features.  *  * This program requests a service called "example".  In order for  * it to function, an entry for it needs to exist in the   * /etc/services file.  The port address for this service can be   * any port number that is likely to be unused, such as 22375,  * for example.  The host on which the server will be runnin  * must also have the same entry (same port number) in its  * /etc/services file.  *  * The "example" service is an example of a simple name server  * application.  The host that is to provide this service is   * required to be in the /etc/hosts file. Also, the host providing  * this service presumably knows the internet addresses of many  * hosts which the local host does not.  Therefore, this program  * will request the internet address of a target host by name from  * the serving host.  The serving host will return the requested  * internet address as a response, and will return an address of   * all ones if it does not recognize the host name.  *  */   #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <netinet/in.h> #include <stdio.h> #include <signal.h> #include <netdb.h>   extern int errno;   int s;                         /* socket descriptor */   struct hostent *hp;            /* pointer to info for nameserver host */ struct servent *sp;            /* pointer to service information */   struct sockaddr_in myaddr_in;  /* for local socket address */ struct sockaddr_in servaddr_in;/* for server socket addres */ struct in_addr reqaddr;        /* for returned internet address */ #define ADDRNOTFOUND 0xffffffff /* value returned for unknown host */ #define RETRIES 5 /* # of times to retry before giving up */   /*  *                      H A N D L E R  *  *      This routine is the signal handler for the alarm signal.  *      It simply re-installs itself as the handler and returns.  */ handler() {         signal(SIGALRM, handler); }   /*  *                      M A I N  *  * This routine is the client which requests service from  * the remote "example server".  It will send a message to the  * remote nameserver requesting the internet address corresponding  * to a given hostname. The server will look up the name, and  * return its internet address. The returned address will be  * written to stdout.  *  * The name of the system to which the requests will be sent is  * given as the first parameter to the command.  The second  * parameter should be the name of the target host for which the  * internet address is sought.  */ main(argc, argv) int argc; char *argv[]; {         int i;         int retry = RETRIES;          /* holds the retry count */         char *inet_ntoa();           if (argc != 3) {             fprintf(stderr, "Usage:  %s <nameserver> <target>\n",                     argv[0]);             exit(1);         }               /* clear out address structures */         memset ((char *)&myaddr_in, 0, sizeof(struct sockaddr_in));         memset ((char *)&servaddr_in, 0, sizeof(struct sockaddr_in));                             /* Set up the server address. */         servaddr_in.sin_family = AF_INET;             /* Get the host info for the server's hostname that the              * user passed in.              */         hp = gethostbyname (argv[1]);         if (hp == NULL) {                 fprintf(stderr, "%s: %s not found in /etc/hosts\n",                                 argv[0], argv[1]);                 exit(1);         }         servaddr_in.sin_addr.s_addr = ((struct in_addr *)                                       (hp->h_addr))->s_addr;                 /* Find the information for the "example" server                  * in order to get the needed port number.                  */         sp = getservbyname ("example", "udp");         if (sp == NULL) {             fprintf(stderr, "%s: example not found in /etc/services\n",                                 argv[0]);                 exit(1);         }         servaddr_in.sin_port = sp->s_port;                   /* Create the socket. */         s = socket (AF_INET, SOCK_DGRAM, 0);         if (s == -1) {                 perror(argv[0]);                 fprintf(stderr, "%s: unable to create socket\n", argv[0]);                 exit(1);         }                /* Bind socket to some local address so that the                 * server can send the reply back.  A port number                 * of zero will be used so that the system will                 * assign any available port number.  An address                 * of INADDR_ANY will be used so we do not have to                 * look up the internet address of the local host.                 */         myaddr_in.sin_family = AF_INET;         myaddr_in.sin_port = 0;         myaddr_in.sin_addr.s_addr = INADDR_ANY;         if (bind(s, &myaddr_in, sizeof(struct sockaddr_in)) == -1) {                 perror(argv[0]);                 fprintf(stderr, "%s: unable to bind socket\n", argv[0]);                 exit(1);         }                 /* Set up alarm signal handler. */         signal(SIGALRM, handler);                                 /* Send the request to the nameserver. */ again:  if (sendto (s, argv[2], strlen(argv[2]), 0, &servaddr_in,                                 sizeof(struct sockaddr_in)) == -1) {                 perror(argv[0]);                 fprintf(stderr, "%s: unable to send request\n", argv[0]);                 exit(1);         }                 /* Set up a timeout so I don't hang in case the packet                  * gets lost.  After all, UDP does not guarantee                  * delivery.                  */         alarm(5);                 /* Wait for the reply to come in.  We assume that                  * no messages will come from any other source,                  * so that we do not need to do a recvfrom nor                  * check the responder's address.                  */        if (recv (s, &reqaddr, sizeof(struct in_addr), 0) == -1) {                 if (errno == EINTR) {                          /* Alarm went off & aborted the receive.                           * Need to retry the request if we have                           * not already exceeded the retry limit.                           */                         if (—retry) {                                 goto again;                         } else {                                printf("Unable to get response from");                                printf(" %s after %d attempts.\n",                                               argv[1], RETRIES);                                exit(1);                         }                 } else {                       perror(argv[0]);                       fprintf(stderr, "%s: unable to receive response\n",                                                        argv[0]);                       exit(1);                       }                 }                 alarm(0);                       /* Print out response. */                 if (reqaddr.s_addr == ADDRNOTFOUND) {                       printf("Host %s unknown by nameserver %s.\n", argv[2],                                                    argv[1]);                       exit(1);                 } else {                       printf("Address for %s is %s.\n", argv[2],                         inet_ntoa(reqaddr));                 } }  |