1cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/******************************************************************************/
2cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*                                                                            */
3cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   Copyright (c) International Business Machines  Corp., 2005               */
4cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*                                                                            */
5cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   This program is free software;  you can redistribute it and/or modify    */
6cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   it under the terms of the GNU General Public License as published by     */
7cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   the Free Software Foundation; either version 2 of the License, or        */
8cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   (at your option) any later version.                                      */
9cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*                                                                            */
10cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   This program is distributed in the hope that it will be useful,          */
11cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   but WITHOUT ANY WARRANTY;  without even the implied warranty of          */
12cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                */
13cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   the GNU General Public License for more details.                         */
14cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*                                                                            */
15cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   You should have received a copy of the GNU General Public License        */
16cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*   along with this program;  if not, write to the Free Software             */
174548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao/*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA  */
18cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*                                                                            */
19cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/******************************************************************************/
20cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
21cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
22cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * File:
23cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *	ns-udpclient.c
24cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
25cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Description:
26cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *	This is UDP traffic client.
27cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *	Send UDP datagram to a server, then receive datagram from it
28cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
29cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Author:
30cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *	Mitsuru Chinen <mitch@jp.ibm.com>
31cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
32cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * History:
33cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *	Oct 19 2005 - Created (Mitsuru Chinen)
34cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *---------------------------------------------------------------------------*/
35cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
36cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include "ns-traffic.h"
37cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
38cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
39cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Fixed value
40cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
41cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#define MESSAGE_LEN 1000	/* The length of message */
42cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#define RECVFROM_TIMEOUT  1	/* Timeout length of recvfrom() */
43cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
44cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
45cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Gloval variables
46cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
47cd30c339dae692a3eb5c5fc55f70726457f4756bmridgestruct sigaction handler;	/* Behavior for a signal */
48cd30c339dae692a3eb5c5fc55f70726457f4756bmridgeint catch_sigalrm;		/* When catch the SIGALRM, set to non-zero */
49cd30c339dae692a3eb5c5fc55f70726457f4756bmridgeint catch_sighup;		/* When catch the SIGHUP, set to non-zero */
50cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
51cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
52cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Standard Header Files
53cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
54cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <stdio.h>
55cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <stdlib.h>
56cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <string.h>
57cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <errno.h>
58cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <fcntl.h>
59cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <netdb.h>
60cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <time.h>
61cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <unistd.h>
62cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/socket.h>
63cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/stat.h>
64cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/types.h>
65cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/wait.h>
66cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <netinet/in.h>
67cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
68cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
69cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Function: usage()
702c28215423293e443469a07ae7011135d058b671Garrett Cooper *
71cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Descripton:
72cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  Print the usage of this program. Then, terminate this program with
73cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  the specified exit value.
74cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
75cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Argument:
76cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  exit_value:	exit value
77cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
78cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Return value:
79cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  This function does not return.
80cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
81354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid usage(char *program_name, int exit_value)
82cd30c339dae692a3eb5c5fc55f70726457f4756bmridge{
83354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	FILE *stream = stdout;	/* stream where the usage is output */
84354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (exit_value == EXIT_FAILURE)
86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		stream = stderr;
87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	fprintf(stream, "%s [OPTION]\n"
89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-S\tname or IP address of the server\n"
90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-f\tprotocol family\n"
91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t\t  4 : IPv4\n"
92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t\t  6 : IPv6\n"
93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-p\tport number\n"
94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-b\twork in the background\n"
95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-d\tdisplay debug informations\n"
96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		"\t-h\tdisplay this usage\n", program_name);
97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	exit(exit_value);
98cd30c339dae692a3eb5c5fc55f70726457f4756bmridge}
99cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
100cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
101cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Function: set_signal_flag()
102cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
103cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Description:
104cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  This function sets global variables accordig to signal
105cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
106cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Argument:
107cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  type: type of signal
108cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
109cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Return value:
110cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  None
111cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid set_signal_flag(int type)
113cd30c339dae692a3eb5c5fc55f70726457f4756bmridge{
114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (debug)
115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Catch signal. type is %d\n", type);
116cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	switch (type) {
118cd30c339dae692a3eb5c5fc55f70726457f4756bmridge	case SIGHUP:
119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		catch_sighup = 1;
120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		handler.sa_handler = SIG_IGN;
121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (sigaction(type, &handler, NULL) < 0)
122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fatal_error("sigaction()");
123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		break;
124cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
125cd30c339dae692a3eb5c5fc55f70726457f4756bmridge	case SIGALRM:
126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		catch_sigalrm = 1;
127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		break;
128cd30c339dae692a3eb5c5fc55f70726457f4756bmridge	default:
129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "Unexpected signal (%d) is caught\n", type);
130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(EXIT_FAILURE);
131354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
132cd30c339dae692a3eb5c5fc55f70726457f4756bmridge}
133cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
134cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/*
135cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
136cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *  Function: main()
137cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *
138cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */
139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[])
140cd30c339dae692a3eb5c5fc55f70726457f4756bmridge{
141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *program_name = argv[0];
142354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int optc;		/* option */
143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
144354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sa_family_t family;	/* protocol family */
145354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *server_name;	/* Name (or IP address) of the server */
146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *portnum;		/* port number in string representation */
147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int sock_fd;		/* socket descriptor to access */
149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int on;			/* on/off at an socket option */
150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct addrinfo hints;	/* hints for getaddrinfo() */
152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	struct addrinfo *res;	/* pointer to addrinfo structure */
153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int err;		/* return value of getaddrinfo */
154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *message;		/* Pointer to the message */
156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	char *recvbuf = NULL;	/* Pointer to the message */
157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	int background = 0;	/* work in the background if non-zero */
159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	debug = 0;
161354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Initilalize the client information */
163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	family = PF_UNSPEC;
164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	server_name = NULL;
165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	portnum = NULL;
166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Retrieve the options */
168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	while ((optc = getopt(argc, argv, "S:f:p:bdh")) != EOF) {
169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		switch (optc) {
170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'S':
171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			server_name = strdup(optarg);
172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (server_name == NULL) {
173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr, "strdup() failed.");
174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				exit(EXIT_FAILURE);
175354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
177354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
178354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'f':
179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (strncmp(optarg, "4", 1) == 0)
180354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				family = PF_INET;	/* IPv4 */
181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			else if (strncmp(optarg, "6", 1) == 0)
182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				family = PF_INET6;	/* IPv6 */
183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			else {
184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fprintf(stderr,
185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					"protocol family should be 4 or 6.\n");
186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				usage(program_name, EXIT_FAILURE);
187354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'p':
191354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			{
192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				unsigned long int tmp;
193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				tmp = strtoul(optarg, NULL, 0);
194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				if (tmp < PORTNUMMIN || PORTNUMMAX < tmp) {
195354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					fprintf(stderr,
196354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						"The range of port is from %u to %u\n",
197354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						PORTNUMMIN, PORTNUMMAX);
198354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					usage(program_name, EXIT_FAILURE);
199354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				}
200354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				portnum = strdup(optarg);
201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
202354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'b':
205354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			background = 1;
206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
208354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'd':
209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			debug = 1;
210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		case 'h':
213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			usage(program_name, EXIT_SUCCESS);
214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		default:
217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			usage(program_name, EXIT_FAILURE);
218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		}
219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2202c28215423293e443469a07ae7011135d058b671Garrett Cooper
221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Check the family is specified. */
222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (family == PF_UNSPEC) {
223354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "protocol family isn't specified.\n");
224354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
225354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2262c28215423293e443469a07ae7011135d058b671Garrett Cooper
227354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Check the server name is specified. */
228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (server_name == NULL) {
229354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "server name isn't specified.\n");
230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
232cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
233354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Check the port number is specified. */
234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (portnum == NULL) {
235354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "port number isn't specified.\n");
236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		usage(program_name, EXIT_FAILURE);
237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2382c28215423293e443469a07ae7011135d058b671Garrett Cooper
239354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* If -b option is specified, work as a daemon */
240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (background)
241354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (daemon(0, 0) < 0)
242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fatal_error("daemon()");
243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
244354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Set a signal handler against SIGALRM */
245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_handler = set_signal_flag;
246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_flags = 0;
247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigfillset(&handler.sa_mask) < 0)
248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigfillset()");
249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigaction(SIGALRM, &handler, NULL) < 0)
250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigaction()");
2512c28215423293e443469a07ae7011135d058b671Garrett Cooper
252354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* At first, SIGHUP are Ignored. */
253354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_handler = SIG_IGN;
254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigaction(SIGHUP, &handler, NULL) < 0)
255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigaction()");
256cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Set the hints to addrinfo() */
258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	memset(&hints, '\0', sizeof(struct addrinfo));
259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	hints.ai_family = family;
260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	hints.ai_socktype = SOCK_DGRAM;
261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	hints.ai_protocol = IPPROTO_UDP;
262cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	err = getaddrinfo(server_name, portnum, &hints, &res);
264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (err) {
265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err));
266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(EXIT_FAILURE);
267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
268354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (res->ai_next) {
269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "getaddrinfo(): multiple address is found.");
270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(EXIT_FAILURE);
271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
2722c28215423293e443469a07ae7011135d058b671Garrett Cooper
273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Create a socket */
274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	sock_fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sock_fd < 0)
276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("socket()");
277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Enable to reuse the socket */
279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	on = 1;
280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)))
281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("setsockopt()");
282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Create a message */
284d218f348c12b42a78fa0306d9a033bfa4f67238bCyril Hrubis	message = malloc(MESSAGE_LEN);
285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (debug) {
286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		strncpy(message, "Hello!", MESSAGE_LEN);
287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		message[MESSAGE_LEN - 1] = '\0';
288354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
289cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/* Prepare the buffer to store the received message */
291d218f348c12b42a78fa0306d9a033bfa4f67238bCyril Hrubis	recvbuf = malloc(MESSAGE_LEN + 1);
292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (recvbuf == NULL) {
293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fprintf(stderr, "malloc() is failed.\n");
294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		exit(EXIT_FAILURE);
295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	}
296cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
297354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	/*
298354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 * Loop for access to the server
299354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	 */
300354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	handler.sa_handler = set_signal_flag;
301354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	if (sigaction(SIGHUP, &handler, NULL) < 0)
302354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		fatal_error("sigaction()");
303354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	for (;;) {
304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		int recvlen;	/* lenght of recevied message */
305354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		struct sockaddr_storage from_addr;	/* address of a client */
306354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		socklen_t from_addr_len;	/* length of `client_addr' */
307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
308354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Send the message to the server */
309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (sendto(sock_fd, message, MESSAGE_LEN, 0,
310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			   res->ai_addr, res->ai_addrlen) != MESSAGE_LEN) {
311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (catch_sighup)
312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				break;
313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			else
314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				fatal_error("sendto()");
315cd30c339dae692a3eb5c5fc55f70726457f4756bmridge		}
3162c28215423293e443469a07ae7011135d058b671Garrett Cooper
317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Receive the response from the server */
318354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		from_addr_len = sizeof(from_addr);
319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		alarm(RECVFROM_TIMEOUT);
320354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if ((recvlen = recvfrom(sock_fd, recvbuf, MESSAGE_LEN, 0,
321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					(struct sockaddr *)&from_addr,
322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					&from_addr_len)) < 0) {
323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			if (errno == EINTR) {
324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				if (catch_sighup) {
325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					break;
326354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				} else if (catch_sigalrm) {
327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					if (debug)
328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao						fprintf(stderr,
329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao							"recvfrom() is timeout\n");
330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao					continue;
331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao				}
332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			}
333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fatal_error("recvfrom()");
334cd30c339dae692a3eb5c5fc55f70726457f4756bmridge		}
335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		alarm(0);
336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		recvbuf[recvlen] = '\0';
337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (debug)
338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			fprintf(stderr, "Message is %s\n", recvbuf);
339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao
340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		/* Catch sighup */
341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao		if (catch_sighup)
342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao			break;
343cd30c339dae692a3eb5c5fc55f70726457f4756bmridge	}
344cd30c339dae692a3eb5c5fc55f70726457f4756bmridge
345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao	exit(EXIT_SUCCESS);
346ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
347