1f08c3bdfSopenharmony_ci/******************************************************************************/ 2f08c3bdfSopenharmony_ci/* */ 3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines Corp., 2006 */ 4f08c3bdfSopenharmony_ci/* */ 5f08c3bdfSopenharmony_ci/* This program is free software; you can redistribute it and/or modify */ 6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by */ 7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or */ 8f08c3bdfSopenharmony_ci/* (at your option) any later version. */ 9f08c3bdfSopenharmony_ci/* */ 10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful, */ 11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details. */ 14f08c3bdfSopenharmony_ci/* */ 15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License */ 16f08c3bdfSopenharmony_ci/* along with this program; if not, write to the Free Software */ 17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18f08c3bdfSopenharmony_ci/* */ 19f08c3bdfSopenharmony_ci/******************************************************************************/ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/* 22f08c3bdfSopenharmony_ci * File: 23f08c3bdfSopenharmony_ci * ns-udpsender.c 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Description: 26f08c3bdfSopenharmony_ci * This is UDP datagram sender (not only unicast but also multicast) 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * Author: 29f08c3bdfSopenharmony_ci * Mitsuru Chinen <mitch@jp.ibm.com> 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * History: 32f08c3bdfSopenharmony_ci * Mar 17 2006 - Created (Mitsuru Chinen) 33f08c3bdfSopenharmony_ci *---------------------------------------------------------------------------*/ 34f08c3bdfSopenharmony_ci 35f08c3bdfSopenharmony_ci/* 36f08c3bdfSopenharmony_ci * Header Files 37f08c3bdfSopenharmony_ci */ 38f08c3bdfSopenharmony_ci#include <stdio.h> 39f08c3bdfSopenharmony_ci#include <stdlib.h> 40f08c3bdfSopenharmony_ci#include <string.h> 41f08c3bdfSopenharmony_ci#include <errno.h> 42f08c3bdfSopenharmony_ci#include <netdb.h> 43f08c3bdfSopenharmony_ci#include <signal.h> 44f08c3bdfSopenharmony_ci#include <time.h> 45f08c3bdfSopenharmony_ci#include <unistd.h> 46f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 47f08c3bdfSopenharmony_ci#include <sys/socket.h> 48f08c3bdfSopenharmony_ci#include <sys/types.h> 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci#include "ns-traffic.h" 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_ci/* 53f08c3bdfSopenharmony_ci * Structure Definitions 54f08c3bdfSopenharmony_ci */ 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistruct udp_info { 57f08c3bdfSopenharmony_ci int sd; 58f08c3bdfSopenharmony_ci int is_multicast; 59f08c3bdfSopenharmony_ci sa_family_t family; 60f08c3bdfSopenharmony_ci char *ifname; 61f08c3bdfSopenharmony_ci char *dst_name; 62f08c3bdfSopenharmony_ci char *dst_port; 63f08c3bdfSopenharmony_ci struct addrinfo addr_info; 64f08c3bdfSopenharmony_ci unsigned char *msg; 65f08c3bdfSopenharmony_ci size_t msgsize; 66f08c3bdfSopenharmony_ci double timeout; 67f08c3bdfSopenharmony_ci}; 68f08c3bdfSopenharmony_ci 69f08c3bdfSopenharmony_ci/* 70f08c3bdfSopenharmony_ci * Gloval variables 71f08c3bdfSopenharmony_ci */ 72f08c3bdfSopenharmony_cichar *program_name; /* program name */ 73f08c3bdfSopenharmony_cistruct sigaction handler; /* Behavior for a signal */ 74f08c3bdfSopenharmony_ciint catch_sighup; /* When catch the SIGHUP, set to non-zero */ 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci/* 77f08c3bdfSopenharmony_ci * Function: usage() 78f08c3bdfSopenharmony_ci * 79f08c3bdfSopenharmony_ci * Descripton: 80f08c3bdfSopenharmony_ci * Print the usage of this program. Then, terminate this program with 81f08c3bdfSopenharmony_ci * the specified exit value. 82f08c3bdfSopenharmony_ci * 83f08c3bdfSopenharmony_ci * Argument: 84f08c3bdfSopenharmony_ci * exit_value: exit value 85f08c3bdfSopenharmony_ci * 86f08c3bdfSopenharmony_ci * Return value: 87f08c3bdfSopenharmony_ci * This function does not return. 88f08c3bdfSopenharmony_ci */ 89f08c3bdfSopenharmony_civoid usage(char *program_name, int exit_value) 90f08c3bdfSopenharmony_ci{ 91f08c3bdfSopenharmony_ci FILE *stream = stdout; /* stream where the usage is output */ 92f08c3bdfSopenharmony_ci 93f08c3bdfSopenharmony_ci if (exit_value == EXIT_FAILURE) 94f08c3bdfSopenharmony_ci stream = stderr; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci fprintf(stream, "%s [OPTION]\n" 97f08c3bdfSopenharmony_ci "\t-f num\ttprotocol family\n" 98f08c3bdfSopenharmony_ci "\t\t 4 : IPv4\n" 99f08c3bdfSopenharmony_ci "\t\t 6 : IPv6\n" 100f08c3bdfSopenharmony_ci "\t-D addr\tIP address of the destination host\n" 101f08c3bdfSopenharmony_ci "\t-p num\tport number of the destination host\n" 102f08c3bdfSopenharmony_ci "\t-s size\tdata size of UDP payload\n" 103f08c3bdfSopenharmony_ci "\t-t value\ttimeout [sec]\n" 104f08c3bdfSopenharmony_ci "\t-o\t\tsend only one UDP datagram\n" 105f08c3bdfSopenharmony_ci "\t-b\t\twork in the background\n" 106f08c3bdfSopenharmony_ci "\t-d\t\tdisplay debug informations\n" 107f08c3bdfSopenharmony_ci "\t-h\t\tdisplay this usage\n" 108f08c3bdfSopenharmony_ci "\n" 109f08c3bdfSopenharmony_ci "\t[options for multicast]\n" 110f08c3bdfSopenharmony_ci "\t -m\t\tsend multicast datagrams\n" 111f08c3bdfSopenharmony_ci "\t -I if_name\tinterface name of the source host\n", 112f08c3bdfSopenharmony_ci program_name); 113f08c3bdfSopenharmony_ci exit(exit_value); 114f08c3bdfSopenharmony_ci} 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci/* 117f08c3bdfSopenharmony_ci * Function: set_signal_flag() 118f08c3bdfSopenharmony_ci * 119f08c3bdfSopenharmony_ci * Description: 120f08c3bdfSopenharmony_ci * This function sets global variables accordig to signal 121f08c3bdfSopenharmony_ci * 122f08c3bdfSopenharmony_ci * Argument: 123f08c3bdfSopenharmony_ci * type: type of signal 124f08c3bdfSopenharmony_ci * 125f08c3bdfSopenharmony_ci * Return value: 126f08c3bdfSopenharmony_ci * None 127f08c3bdfSopenharmony_ci */ 128f08c3bdfSopenharmony_civoid set_signal_flag(int type) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci if (debug) 131f08c3bdfSopenharmony_ci fprintf(stderr, "Catch signal. type is %d\n", type); 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci switch (type) { 134f08c3bdfSopenharmony_ci case SIGHUP: 135f08c3bdfSopenharmony_ci catch_sighup = 1; 136f08c3bdfSopenharmony_ci handler.sa_handler = SIG_IGN; 137f08c3bdfSopenharmony_ci if (sigaction(type, &handler, NULL) < 0) 138f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 139f08c3bdfSopenharmony_ci break; 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci default: 142f08c3bdfSopenharmony_ci fprintf(stderr, "Unexpected signal (%d) is caught\n", type); 143f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 144f08c3bdfSopenharmony_ci } 145f08c3bdfSopenharmony_ci} 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ci/* 148f08c3bdfSopenharmony_ci * Function: parse_options() 149f08c3bdfSopenharmony_ci * 150f08c3bdfSopenharmony_ci * Description: 151f08c3bdfSopenharmony_ci * This function parse the options 152f08c3bdfSopenharmony_ci * 153f08c3bdfSopenharmony_ci * Argument: 154f08c3bdfSopenharmony_ci * argc: the number of argument 155f08c3bdfSopenharmony_ci * argv: arguments 156f08c3bdfSopenharmony_ci * udp_p: pointer to the data of udp datagram 157f08c3bdfSopenharmony_ci * bg_p: pointer to the flag of working in backgrond 158f08c3bdfSopenharmony_ci * 159f08c3bdfSopenharmony_ci * Return value: 160f08c3bdfSopenharmony_ci * None 161f08c3bdfSopenharmony_ci */ 162f08c3bdfSopenharmony_civoid parse_options(int argc, char *argv[], struct udp_info *udp_p, int *bg_p) 163f08c3bdfSopenharmony_ci{ 164f08c3bdfSopenharmony_ci int optc; /* option */ 165f08c3bdfSopenharmony_ci unsigned long opt_ul; /* option value in unsigned long */ 166f08c3bdfSopenharmony_ci double opt_d; /* option value in double */ 167f08c3bdfSopenharmony_ci int is_specified_family = 0; 168f08c3bdfSopenharmony_ci int is_specified_daddr = 0; 169f08c3bdfSopenharmony_ci int is_specified_port = 0; 170f08c3bdfSopenharmony_ci 171f08c3bdfSopenharmony_ci while ((optc = getopt(argc, argv, "f:D:p:s:t:obdhmI:")) != EOF) { 172f08c3bdfSopenharmony_ci switch (optc) { 173f08c3bdfSopenharmony_ci case 'f': 174f08c3bdfSopenharmony_ci if (optarg[0] == '4') 175f08c3bdfSopenharmony_ci udp_p->family = PF_INET; /* IPv4 */ 176f08c3bdfSopenharmony_ci else if (optarg[0] == '6') 177f08c3bdfSopenharmony_ci udp_p->family = PF_INET6; /* IPv6 */ 178f08c3bdfSopenharmony_ci else { 179f08c3bdfSopenharmony_ci fprintf(stderr, 180f08c3bdfSopenharmony_ci "protocol family should be 4 or 6.\n"); 181f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 182f08c3bdfSopenharmony_ci } 183f08c3bdfSopenharmony_ci is_specified_family = 1; 184f08c3bdfSopenharmony_ci break; 185f08c3bdfSopenharmony_ci 186f08c3bdfSopenharmony_ci case 'D': 187f08c3bdfSopenharmony_ci udp_p->dst_name = strdup(optarg); 188f08c3bdfSopenharmony_ci if (udp_p->dst_name == NULL) 189f08c3bdfSopenharmony_ci fatal_error("strdup() failed."); 190f08c3bdfSopenharmony_ci is_specified_daddr = 1; 191f08c3bdfSopenharmony_ci break; 192f08c3bdfSopenharmony_ci 193f08c3bdfSopenharmony_ci case 'p': 194f08c3bdfSopenharmony_ci opt_ul = strtoul(optarg, NULL, 0); 195f08c3bdfSopenharmony_ci if (opt_ul < 1 || PORTNUMMAX < opt_ul) { 196f08c3bdfSopenharmony_ci fprintf(stderr, 197f08c3bdfSopenharmony_ci "The range of port is from %u to %u\n", 198f08c3bdfSopenharmony_ci 1, PORTNUMMAX); 199f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 200f08c3bdfSopenharmony_ci } 201f08c3bdfSopenharmony_ci udp_p->dst_port = strdup(optarg); 202f08c3bdfSopenharmony_ci is_specified_port = 1; 203f08c3bdfSopenharmony_ci break; 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci case 's': 206f08c3bdfSopenharmony_ci opt_ul = strtoul(optarg, NULL, 0); 207f08c3bdfSopenharmony_ci udp_p->msgsize = opt_ul; 208f08c3bdfSopenharmony_ci break; 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci case 't': 211f08c3bdfSopenharmony_ci opt_d = strtod(optarg, NULL); 212f08c3bdfSopenharmony_ci if (opt_d < 0.0) { 213f08c3bdfSopenharmony_ci fprintf(stderr, 214f08c3bdfSopenharmony_ci "Timeout should be positive value\n"); 215f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 216f08c3bdfSopenharmony_ci } 217f08c3bdfSopenharmony_ci udp_p->timeout = opt_d; 218f08c3bdfSopenharmony_ci break; 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci case 'o': 221f08c3bdfSopenharmony_ci udp_p->timeout = -1.0; 222f08c3bdfSopenharmony_ci break; 223f08c3bdfSopenharmony_ci 224f08c3bdfSopenharmony_ci case 'b': 225f08c3bdfSopenharmony_ci *bg_p = 1; 226f08c3bdfSopenharmony_ci break; 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci case 'd': 229f08c3bdfSopenharmony_ci debug = 1; 230f08c3bdfSopenharmony_ci break; 231f08c3bdfSopenharmony_ci 232f08c3bdfSopenharmony_ci case 'h': 233f08c3bdfSopenharmony_ci usage(program_name, EXIT_SUCCESS); 234f08c3bdfSopenharmony_ci break; 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci /* Options for multicast */ 237f08c3bdfSopenharmony_ci case 'm': 238f08c3bdfSopenharmony_ci udp_p->is_multicast = 1; 239f08c3bdfSopenharmony_ci break; 240f08c3bdfSopenharmony_ci 241f08c3bdfSopenharmony_ci case 'I': 242f08c3bdfSopenharmony_ci udp_p->ifname = strdup(optarg); 243f08c3bdfSopenharmony_ci if (udp_p->dst_name == NULL) 244f08c3bdfSopenharmony_ci fatal_error("strdup() failed."); 245f08c3bdfSopenharmony_ci break; 246f08c3bdfSopenharmony_ci 247f08c3bdfSopenharmony_ci default: 248f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 249f08c3bdfSopenharmony_ci } 250f08c3bdfSopenharmony_ci } 251f08c3bdfSopenharmony_ci 252f08c3bdfSopenharmony_ci if (!is_specified_family) { 253f08c3bdfSopenharmony_ci fprintf(stderr, "protocol family is not specified\n"); 254f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 255f08c3bdfSopenharmony_ci } 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_ci if (!is_specified_daddr) { 258f08c3bdfSopenharmony_ci fprintf(stderr, "desttinaion IP address is not specified\n"); 259f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 260f08c3bdfSopenharmony_ci } 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci if (!is_specified_port) { 263f08c3bdfSopenharmony_ci fprintf(stderr, "destination port is not specified\n"); 264f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 265f08c3bdfSopenharmony_ci } 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci if (udp_p->is_multicast) { 268f08c3bdfSopenharmony_ci if (udp_p->ifname == NULL) { 269f08c3bdfSopenharmony_ci fprintf(stderr, 270f08c3bdfSopenharmony_ci "interface name is not specified with multicast\n"); 271f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 272f08c3bdfSopenharmony_ci } 273f08c3bdfSopenharmony_ci } 274f08c3bdfSopenharmony_ci} 275f08c3bdfSopenharmony_ci 276f08c3bdfSopenharmony_ci/* 277f08c3bdfSopenharmony_ci * Function: create_udp_datagram() 278f08c3bdfSopenharmony_ci * 279f08c3bdfSopenharmony_ci * Description: 280f08c3bdfSopenharmony_ci * This function creates udp datagram 281f08c3bdfSopenharmony_ci * 282f08c3bdfSopenharmony_ci * Argument: 283f08c3bdfSopenharmony_ci * udp_p: pointer to data of udp data structure 284f08c3bdfSopenharmony_ci * 285f08c3bdfSopenharmony_ci * Return value: 286f08c3bdfSopenharmony_ci * None 287f08c3bdfSopenharmony_ci */ 288f08c3bdfSopenharmony_civoid create_udp_datagram(struct udp_info *udp_p) 289f08c3bdfSopenharmony_ci{ 290f08c3bdfSopenharmony_ci struct addrinfo hints; /* hints for getaddrinfo() */ 291f08c3bdfSopenharmony_ci struct addrinfo *res; /* pointer to addrinfo structure */ 292f08c3bdfSopenharmony_ci struct ifreq ifinfo; /* Interface information */ 293f08c3bdfSopenharmony_ci int err; /* return value of getaddrinfo */ 294f08c3bdfSopenharmony_ci int on; /* variable for socket option */ 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_ci /* Set the hints to addrinfo() */ 297f08c3bdfSopenharmony_ci memset(&hints, '\0', sizeof(struct addrinfo)); 298f08c3bdfSopenharmony_ci hints.ai_family = udp_p->family; 299f08c3bdfSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 300f08c3bdfSopenharmony_ci hints.ai_protocol = IPPROTO_UDP; 301f08c3bdfSopenharmony_ci 302f08c3bdfSopenharmony_ci /* Get the address information */ 303f08c3bdfSopenharmony_ci err = getaddrinfo(udp_p->dst_name, udp_p->dst_port, &hints, &res); 304f08c3bdfSopenharmony_ci if (err) { 305f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err)); 306f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 307f08c3bdfSopenharmony_ci } 308f08c3bdfSopenharmony_ci if (res->ai_next) { 309f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): multiple address is found."); 310f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 311f08c3bdfSopenharmony_ci } 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci /* Create a socket */ 314f08c3bdfSopenharmony_ci udp_p->sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 315f08c3bdfSopenharmony_ci if (udp_p->sd < 0) 316f08c3bdfSopenharmony_ci fatal_error("socket()"); 317f08c3bdfSopenharmony_ci 318f08c3bdfSopenharmony_ci /* Enable to reuse the socket */ 319f08c3bdfSopenharmony_ci on = 1; 320f08c3bdfSopenharmony_ci if (setsockopt(udp_p->sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) 321f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci /* In multicast case, specify the interface for outgoing datagrams */ 324f08c3bdfSopenharmony_ci if (udp_p->is_multicast) { 325f08c3bdfSopenharmony_ci struct ip_mreqn mcast_req, *req_p = &mcast_req; 326f08c3bdfSopenharmony_ci int ifindex, *id_p = &ifindex; 327f08c3bdfSopenharmony_ci 328f08c3bdfSopenharmony_ci get_ifinfo(&ifinfo, udp_p->sd, udp_p->ifname, SIOCGIFINDEX); 329f08c3bdfSopenharmony_ci ifindex = ifinfo.ifr_ifindex; 330f08c3bdfSopenharmony_ci 331f08c3bdfSopenharmony_ci switch (udp_p->family) { 332f08c3bdfSopenharmony_ci case PF_INET: /* IPv4 */ 333f08c3bdfSopenharmony_ci req_p->imr_multiaddr = 334f08c3bdfSopenharmony_ci ((struct sockaddr_in *)(res->ai_addr))->sin_addr; 335f08c3bdfSopenharmony_ci req_p->imr_address.s_addr = htonl(INADDR_ANY); 336f08c3bdfSopenharmony_ci req_p->imr_ifindex = ifindex; 337f08c3bdfSopenharmony_ci if (setsockopt(udp_p->sd, IPPROTO_IP, IP_MULTICAST_IF, 338f08c3bdfSopenharmony_ci req_p, sizeof(struct ip_mreqn))) { 339f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 340f08c3bdfSopenharmony_ci } 341f08c3bdfSopenharmony_ci break; 342f08c3bdfSopenharmony_ci 343f08c3bdfSopenharmony_ci case PF_INET6: /* IPv6 */ 344f08c3bdfSopenharmony_ci if (setsockopt 345f08c3bdfSopenharmony_ci (udp_p->sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, id_p, 346f08c3bdfSopenharmony_ci sizeof(int))) { 347f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 348f08c3bdfSopenharmony_ci } 349f08c3bdfSopenharmony_ci break; 350f08c3bdfSopenharmony_ci } 351f08c3bdfSopenharmony_ci } 352f08c3bdfSopenharmony_ci 353f08c3bdfSopenharmony_ci /* Make the payload */ 354f08c3bdfSopenharmony_ci udp_p->msg = malloc(udp_p->msgsize); 355f08c3bdfSopenharmony_ci if (udp_p->msg == NULL) { 356f08c3bdfSopenharmony_ci fatal_error("malloc()"); 357f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 358f08c3bdfSopenharmony_ci } 359f08c3bdfSopenharmony_ci fill_payload(udp_p->msg, udp_p->msgsize); 360f08c3bdfSopenharmony_ci 361f08c3bdfSopenharmony_ci /* Store addrinfo */ 362f08c3bdfSopenharmony_ci memcpy(&(udp_p->addr_info), res, sizeof(struct addrinfo)); 363f08c3bdfSopenharmony_ci freeaddrinfo(res); 364f08c3bdfSopenharmony_ci} 365f08c3bdfSopenharmony_ci 366f08c3bdfSopenharmony_ci/* 367f08c3bdfSopenharmony_ci * Function: send_udp_datagram() 368f08c3bdfSopenharmony_ci * 369f08c3bdfSopenharmony_ci * Description: 370f08c3bdfSopenharmony_ci * This function sends udp datagram 371f08c3bdfSopenharmony_ci * 372f08c3bdfSopenharmony_ci * Argument: 373f08c3bdfSopenharmony_ci * udp_p: pointer to the udp data structure 374f08c3bdfSopenharmony_ci * 375f08c3bdfSopenharmony_ci * Return value: 376f08c3bdfSopenharmony_ci * None 377f08c3bdfSopenharmony_ci */ 378f08c3bdfSopenharmony_civoid send_udp_datagram(struct udp_info *udp_p) 379f08c3bdfSopenharmony_ci{ 380f08c3bdfSopenharmony_ci int retval; 381f08c3bdfSopenharmony_ci double start_time; 382f08c3bdfSopenharmony_ci 383f08c3bdfSopenharmony_ci /* Set singal hander for SIGHUP */ 384f08c3bdfSopenharmony_ci handler.sa_handler = set_signal_flag; 385f08c3bdfSopenharmony_ci handler.sa_flags = 0; 386f08c3bdfSopenharmony_ci if (sigfillset(&handler.sa_mask) < 0) 387f08c3bdfSopenharmony_ci fatal_error("sigfillset()"); 388f08c3bdfSopenharmony_ci if (sigaction(SIGHUP, &handler, NULL) < 0) 389f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 390f08c3bdfSopenharmony_ci 391f08c3bdfSopenharmony_ci /* 392f08c3bdfSopenharmony_ci * loop for sending packets 393f08c3bdfSopenharmony_ci */ 394f08c3bdfSopenharmony_ci start_time = time(NULL); 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci for (;;) { 397f08c3bdfSopenharmony_ci retval = sendto(udp_p->sd, udp_p->msg, udp_p->msgsize, 0, 398f08c3bdfSopenharmony_ci udp_p->addr_info.ai_addr, 399f08c3bdfSopenharmony_ci udp_p->addr_info.ai_addrlen); 400f08c3bdfSopenharmony_ci if (retval != udp_p->msgsize) { 401f08c3bdfSopenharmony_ci if (catch_sighup) 402f08c3bdfSopenharmony_ci break; 403f08c3bdfSopenharmony_ci else 404f08c3bdfSopenharmony_ci fatal_error("sendto()"); 405f08c3bdfSopenharmony_ci } 406f08c3bdfSopenharmony_ci 407f08c3bdfSopenharmony_ci /* Check timeout: 408f08c3bdfSopenharmony_ci If timeout value is negative only send one datagram */ 409f08c3bdfSopenharmony_ci if (udp_p->timeout) 410f08c3bdfSopenharmony_ci if (udp_p->timeout < difftime(time(NULL), start_time)) 411f08c3bdfSopenharmony_ci break; 412f08c3bdfSopenharmony_ci 413f08c3bdfSopenharmony_ci if (catch_sighup) /* catch SIGHUP */ 414f08c3bdfSopenharmony_ci break; 415f08c3bdfSopenharmony_ci } 416f08c3bdfSopenharmony_ci 417f08c3bdfSopenharmony_ci /* Close the socket */ 418f08c3bdfSopenharmony_ci close(udp_p->sd); 419f08c3bdfSopenharmony_ci} 420f08c3bdfSopenharmony_ci 421f08c3bdfSopenharmony_ci/* 422f08c3bdfSopenharmony_ci * 423f08c3bdfSopenharmony_ci * Function: main() 424f08c3bdfSopenharmony_ci * 425f08c3bdfSopenharmony_ci */ 426f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 427f08c3bdfSopenharmony_ci{ 428f08c3bdfSopenharmony_ci struct udp_info udp_data; 429f08c3bdfSopenharmony_ci int background = 0; 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci debug = 0; 432f08c3bdfSopenharmony_ci program_name = strdup(argv[0]); 433f08c3bdfSopenharmony_ci 434f08c3bdfSopenharmony_ci memset(&udp_data, '\0', sizeof(struct udp_info)); 435f08c3bdfSopenharmony_ci parse_options(argc, argv, &udp_data, &background); 436f08c3bdfSopenharmony_ci 437f08c3bdfSopenharmony_ci create_udp_datagram(&udp_data); 438f08c3bdfSopenharmony_ci 439f08c3bdfSopenharmony_ci if (background) /* Work in the background */ 440f08c3bdfSopenharmony_ci if (daemon(0, 0) < 0) 441f08c3bdfSopenharmony_ci fatal_error("daemon()"); 442f08c3bdfSopenharmony_ci 443f08c3bdfSopenharmony_ci send_udp_datagram(&udp_data); 444f08c3bdfSopenharmony_ci 445f08c3bdfSopenharmony_ci exit(EXIT_SUCCESS); 446f08c3bdfSopenharmony_ci} 447