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