ns-icmpv6_sender.c revision ec6edca7aa42b6affd989ef91b5897f96795e40f
197903da2202008733f50e69997029d7a5cfffcb8mreed/******************************************************************************/
297903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
397903da2202008733f50e69997029d7a5cfffcb8mreed/*   Copyright (c) International Business Machines  Corp., 2006               */
497903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
597903da2202008733f50e69997029d7a5cfffcb8mreed/*   This program is free software;  you can redistribute it and/or modify    */
697903da2202008733f50e69997029d7a5cfffcb8mreed/*   it under the terms of the GNU General Public License as published by     */
797903da2202008733f50e69997029d7a5cfffcb8mreed/*   the Free Software Foundation; either version 2 of the License, or        */
897903da2202008733f50e69997029d7a5cfffcb8mreed/*   (at your option) any later version.                                      */
997903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1097903da2202008733f50e69997029d7a5cfffcb8mreed/*   This program is distributed in the hope that it will be useful,          */
1197903da2202008733f50e69997029d7a5cfffcb8mreed/*   but WITHOUT ANY WARRANTY;  without even the implied warranty of          */
1297903da2202008733f50e69997029d7a5cfffcb8mreed/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See                */
1397903da2202008733f50e69997029d7a5cfffcb8mreed/*   the GNU General Public License for more details.                         */
1497903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1597903da2202008733f50e69997029d7a5cfffcb8mreed/*   You should have received a copy of the GNU General Public License        */
1697903da2202008733f50e69997029d7a5cfffcb8mreed/*   along with this program;  if not, write to the Free Software             */
1797903da2202008733f50e69997029d7a5cfffcb8mreed/*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  */
1897903da2202008733f50e69997029d7a5cfffcb8mreed/*                                                                            */
1997903da2202008733f50e69997029d7a5cfffcb8mreed/******************************************************************************/
2097903da2202008733f50e69997029d7a5cfffcb8mreed
2197903da2202008733f50e69997029d7a5cfffcb8mreed/*
2297903da2202008733f50e69997029d7a5cfffcb8mreed * File:
2397903da2202008733f50e69997029d7a5cfffcb8mreed *	ns-icmpv6_sender.c
2497903da2202008733f50e69997029d7a5cfffcb8mreed *
2597903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
2697903da2202008733f50e69997029d7a5cfffcb8mreed *	This is ICMPv6 message (Echo request / MLDv2 query) sender.
2797903da2202008733f50e69997029d7a5cfffcb8mreed *	This utility is also able to set illegal information in the IP header
2897903da2202008733f50e69997029d7a5cfffcb8mreed *
2997903da2202008733f50e69997029d7a5cfffcb8mreed * Author:
3097903da2202008733f50e69997029d7a5cfffcb8mreed *	Mitsuru Chinen <mitch@jp.ibm.com>
3197903da2202008733f50e69997029d7a5cfffcb8mreed *
3297903da2202008733f50e69997029d7a5cfffcb8mreed * History:
3397903da2202008733f50e69997029d7a5cfffcb8mreed *	Mar 15 2006 - Created (Mitsuru Chinen)
3497903da2202008733f50e69997029d7a5cfffcb8mreed *---------------------------------------------------------------------------*/
3597903da2202008733f50e69997029d7a5cfffcb8mreed
3697903da2202008733f50e69997029d7a5cfffcb8mreed/*
3797903da2202008733f50e69997029d7a5cfffcb8mreed * Header Files
3897903da2202008733f50e69997029d7a5cfffcb8mreed */
3997903da2202008733f50e69997029d7a5cfffcb8mreed#include <stdio.h>
4097903da2202008733f50e69997029d7a5cfffcb8mreed#include <stdlib.h>
4197903da2202008733f50e69997029d7a5cfffcb8mreed#include <string.h>
4297903da2202008733f50e69997029d7a5cfffcb8mreed#include <errno.h>
4397903da2202008733f50e69997029d7a5cfffcb8mreed#include <netdb.h>
4497903da2202008733f50e69997029d7a5cfffcb8mreed#include <signal.h>
4597903da2202008733f50e69997029d7a5cfffcb8mreed#include <time.h>
4697903da2202008733f50e69997029d7a5cfffcb8mreed#include <unistd.h>
4797903da2202008733f50e69997029d7a5cfffcb8mreed#include <sys/ioctl.h>
4897903da2202008733f50e69997029d7a5cfffcb8mreed#include <sys/socket.h>
4997903da2202008733f50e69997029d7a5cfffcb8mreed#include <arpa/inet.h>
5097903da2202008733f50e69997029d7a5cfffcb8mreed#include <net/ethernet.h>
5197903da2202008733f50e69997029d7a5cfffcb8mreed#include <netinet/in.h>
5297903da2202008733f50e69997029d7a5cfffcb8mreed
5397903da2202008733f50e69997029d7a5cfffcb8mreed#include "ns-mcast.h"
5497903da2202008733f50e69997029d7a5cfffcb8mreed#include "ns-traffic.h"
5597903da2202008733f50e69997029d7a5cfffcb8mreed
5697903da2202008733f50e69997029d7a5cfffcb8mreed/*
5797903da2202008733f50e69997029d7a5cfffcb8mreed * Structure Definitions
5897903da2202008733f50e69997029d7a5cfffcb8mreed */
5997903da2202008733f50e69997029d7a5cfffcb8mreedstruct icmp6_info {
6097903da2202008733f50e69997029d7a5cfffcb8mreed    struct ip6_datagram pkt;
6197903da2202008733f50e69997029d7a5cfffcb8mreed    struct sockaddr_ll saddr_ll;
6297903da2202008733f50e69997029d7a5cfffcb8mreed    struct sockaddr_ll daddr_ll;
6397903da2202008733f50e69997029d7a5cfffcb8mreed    struct in6_addr saddr;
6497903da2202008733f50e69997029d7a5cfffcb8mreed    struct in6_addr daddr;
6597903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned short int pkt_size;
6697903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned short int data_size;
6797903da2202008733f50e69997029d7a5cfffcb8mreed    double timeout;
6897903da2202008733f50e69997029d7a5cfffcb8mreed    struct timespec interval;
6997903da2202008733f50e69997029d7a5cfffcb8mreed
7097903da2202008733f50e69997029d7a5cfffcb8mreed    u_int16_t fake_flag;
7197903da2202008733f50e69997029d7a5cfffcb8mreed};
7297903da2202008733f50e69997029d7a5cfffcb8mreed
7397903da2202008733f50e69997029d7a5cfffcb8mreed/*
7497903da2202008733f50e69997029d7a5cfffcb8mreed * Gloval variables
7597903da2202008733f50e69997029d7a5cfffcb8mreed */
7697903da2202008733f50e69997029d7a5cfffcb8mreedchar *program_name;		/* program name */
7797903da2202008733f50e69997029d7a5cfffcb8mreedstruct sigaction handler;	/* Behavior for a signal */
7897903da2202008733f50e69997029d7a5cfffcb8mreedint catch_sighup;		/* When catch the SIGHUP, set to non-zero */
7997903da2202008733f50e69997029d7a5cfffcb8mreedstruct in6_addr in6addr_allnodes = IN6ADDR_ALLNODES_MULTICAST_INIT;
8097903da2202008733f50e69997029d7a5cfffcb8mreed
8197903da2202008733f50e69997029d7a5cfffcb8mreed/*
8297903da2202008733f50e69997029d7a5cfffcb8mreed * Function: usage()
8397903da2202008733f50e69997029d7a5cfffcb8mreed *
8497903da2202008733f50e69997029d7a5cfffcb8mreed * Descripton:
8597903da2202008733f50e69997029d7a5cfffcb8mreed *  Print the usage of this program. Then, terminate this program with
8697903da2202008733f50e69997029d7a5cfffcb8mreed *  the specified exit value.
8797903da2202008733f50e69997029d7a5cfffcb8mreed *
8897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
8997903da2202008733f50e69997029d7a5cfffcb8mreed *  exit_value:	exit value
9097903da2202008733f50e69997029d7a5cfffcb8mreed *
9197903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
9297903da2202008733f50e69997029d7a5cfffcb8mreed *  This function does not return.
9397903da2202008733f50e69997029d7a5cfffcb8mreed */
9497903da2202008733f50e69997029d7a5cfffcb8mreedvoid
9597903da2202008733f50e69997029d7a5cfffcb8mreedusage (char *program_name, int exit_value)
9697903da2202008733f50e69997029d7a5cfffcb8mreed{
9797903da2202008733f50e69997029d7a5cfffcb8mreed    FILE *stream = stdout;	/* stream where the usage is output */
9897903da2202008733f50e69997029d7a5cfffcb8mreed
9997903da2202008733f50e69997029d7a5cfffcb8mreed    if (exit_value == EXIT_FAILURE)
10097903da2202008733f50e69997029d7a5cfffcb8mreed	stream = stderr;
10197903da2202008733f50e69997029d7a5cfffcb8mreed
10297903da2202008733f50e69997029d7a5cfffcb8mreed    fprintf (stream, "%s [OPTION]\n"
10397903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-I if_name\tInterface name of the source host\n"
10497903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-S ip_addr\tIPv6 address of the source host\n"
10597903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-M mac_addr\tMAC address of the destination host\n"
10697903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-D ip_addr\tIPv6 address of the destination host\n"
10797903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-t value\ttimeout [sec]\n"
10897903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-w value\tinterval [nanosec]\n"
10997903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-o\t\tsend only one ICMPv6 message\n"
11097903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-b\t\twork in the background\n"
11197903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-d\t\tdisplay debug informations\n"
11297903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t-h\t\tdisplay this usage\n"
11397903da2202008733f50e69997029d7a5cfffcb8mreed		     "\n"
11497903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t[options for echo request]\n"
11597903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -s packetsize\tsize of data (exclude header)\n"
11697903da2202008733f50e69997029d7a5cfffcb8mreed		     "\n"
11797903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t[options for fake]\n"
11897903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -i\t\tbreak IPv6 destination address\n"
11997903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -L\t\tbreak payload length\n"
12097903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -n\t\tbreak next header\n"
12197903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -v\t\tbreak IP version\n"
12297903da2202008733f50e69997029d7a5cfffcb8mreed		     "\n"
12397903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t[options for MLDv2 query]\n"
12497903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -m\t\tsend MLDv2 query\n"
12597903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -a addrs\tcomma separated array of Source Addresses\n"
12697903da2202008733f50e69997029d7a5cfffcb8mreed		     "\t  -r value\tMax Resp Code\n"
12797903da2202008733f50e69997029d7a5cfffcb8mreed			    , program_name);
12897903da2202008733f50e69997029d7a5cfffcb8mreed    exit (exit_value);
12997903da2202008733f50e69997029d7a5cfffcb8mreed}
13097903da2202008733f50e69997029d7a5cfffcb8mreed
13197903da2202008733f50e69997029d7a5cfffcb8mreed/*
13297903da2202008733f50e69997029d7a5cfffcb8mreed * Function: set_signal_flag()
13397903da2202008733f50e69997029d7a5cfffcb8mreed *
13497903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
13597903da2202008733f50e69997029d7a5cfffcb8mreed *  This function sets global variables according to signal
13697903da2202008733f50e69997029d7a5cfffcb8mreed *
13797903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
13897903da2202008733f50e69997029d7a5cfffcb8mreed *  type: type of signal
13997903da2202008733f50e69997029d7a5cfffcb8mreed *
14097903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
14197903da2202008733f50e69997029d7a5cfffcb8mreed *  None
14297903da2202008733f50e69997029d7a5cfffcb8mreed */
14397903da2202008733f50e69997029d7a5cfffcb8mreedvoid
14497903da2202008733f50e69997029d7a5cfffcb8mreedset_signal_flag(int type)
14597903da2202008733f50e69997029d7a5cfffcb8mreed{
14697903da2202008733f50e69997029d7a5cfffcb8mreed    if (debug)
14797903da2202008733f50e69997029d7a5cfffcb8mreed	fprintf(stderr, "Catch signal. type is %d\n", type);
14897903da2202008733f50e69997029d7a5cfffcb8mreed
14997903da2202008733f50e69997029d7a5cfffcb8mreed    switch (type) {
15097903da2202008733f50e69997029d7a5cfffcb8mreed	case SIGHUP:
15197903da2202008733f50e69997029d7a5cfffcb8mreed	    catch_sighup = 1;
15297903da2202008733f50e69997029d7a5cfffcb8mreed	    handler.sa_handler = SIG_IGN;
15397903da2202008733f50e69997029d7a5cfffcb8mreed	    if (sigaction(type, &handler, NULL) < 0)
15497903da2202008733f50e69997029d7a5cfffcb8mreed		fatal_error("sigaction()");
15597903da2202008733f50e69997029d7a5cfffcb8mreed	    break;
15697903da2202008733f50e69997029d7a5cfffcb8mreed
15797903da2202008733f50e69997029d7a5cfffcb8mreed	default:
15897903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "Unexpected signal (%d) is caught\n", type);
15997903da2202008733f50e69997029d7a5cfffcb8mreed	    exit(EXIT_FAILURE);
16097903da2202008733f50e69997029d7a5cfffcb8mreed    }
16197903da2202008733f50e69997029d7a5cfffcb8mreed}
16297903da2202008733f50e69997029d7a5cfffcb8mreed
16397903da2202008733f50e69997029d7a5cfffcb8mreed/*
16497903da2202008733f50e69997029d7a5cfffcb8mreed * Function: specify_hw_addr()
16597903da2202008733f50e69997029d7a5cfffcb8mreed *
16697903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
16797903da2202008733f50e69997029d7a5cfffcb8mreed *  This function specifies the hardware address from the interface name
16897903da2202008733f50e69997029d7a5cfffcb8mreed *
16997903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
17097903da2202008733f50e69997029d7a5cfffcb8mreed *   lladdr_p:	pointer to the sockaddr_ll structure
17197903da2202008733f50e69997029d7a5cfffcb8mreed *    ifname:	interface name where icmpv6 messages go out
17297903da2202008733f50e69997029d7a5cfffcb8mreed *
17397903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
17497903da2202008733f50e69997029d7a5cfffcb8mreed *  None
17597903da2202008733f50e69997029d7a5cfffcb8mreed *
17697903da2202008733f50e69997029d7a5cfffcb8mreed */
17797903da2202008733f50e69997029d7a5cfffcb8mreedvoid
17897903da2202008733f50e69997029d7a5cfffcb8mreedspecify_hw_addr(struct sockaddr_ll *lladdr_p, const char *ifname)
17997903da2202008733f50e69997029d7a5cfffcb8mreed{
18097903da2202008733f50e69997029d7a5cfffcb8mreed    int sock_fd;		/* Socket for ioctl() */
18197903da2202008733f50e69997029d7a5cfffcb8mreed    struct ifreq ifinfo;	/* Interface information */
18297903da2202008733f50e69997029d7a5cfffcb8mreed
18397903da2202008733f50e69997029d7a5cfffcb8mreed    if ((sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0)
18497903da2202008733f50e69997029d7a5cfffcb8mreed	fatal_error("socket()");
18597903da2202008733f50e69997029d7a5cfffcb8mreed
18697903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_family    = AF_PACKET;	/* Always AF_PACKET */
18797903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_protocol  = htons(ETH_P_IPV6);	/* IPv6 */
18897903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_hatype    = ARPHRD_ETHER;	/* Header type */
18997903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_pkttype   = PACKET_HOST;	/* Packet type */
19097903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_halen	    = ETH_ALEN;		/* Length of address */
19197903da2202008733f50e69997029d7a5cfffcb8mreed
19297903da2202008733f50e69997029d7a5cfffcb8mreed    /* Get the MAC address of the interface at source host */
19397903da2202008733f50e69997029d7a5cfffcb8mreed    get_ifinfo(&ifinfo, sock_fd, ifname, SIOCGIFHWADDR);
19497903da2202008733f50e69997029d7a5cfffcb8mreed    memcpy(lladdr_p->sll_addr, ifinfo.ifr_hwaddr.sa_data, ETH_ALEN);
19597903da2202008733f50e69997029d7a5cfffcb8mreed
19697903da2202008733f50e69997029d7a5cfffcb8mreed    /* Get the interface index */
19797903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_ifindex = if_nametoindex(ifname);
19897903da2202008733f50e69997029d7a5cfffcb8mreed    close(sock_fd);
19997903da2202008733f50e69997029d7a5cfffcb8mreed}
20097903da2202008733f50e69997029d7a5cfffcb8mreed
20197903da2202008733f50e69997029d7a5cfffcb8mreed/*
20297903da2202008733f50e69997029d7a5cfffcb8mreed * Function: calc_hd_mcastaddr
20397903da2202008733f50e69997029d7a5cfffcb8mreed *
20497903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
20597903da2202008733f50e69997029d7a5cfffcb8mreed *  This function calculate multicast hardware address from IPv6
20697903da2202008733f50e69997029d7a5cfffcb8mreed *  multicast address
20797903da2202008733f50e69997029d7a5cfffcb8mreed *
20897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
20997903da2202008733f50e69997029d7a5cfffcb8mreed *   lladdr_p:	pointer to the sockaddr_ll structure
21097903da2202008733f50e69997029d7a5cfffcb8mreed *    addr_p:	pointer to the in6_addr structure
21197903da2202008733f50e69997029d7a5cfffcb8mreed *
21297903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
21397903da2202008733f50e69997029d7a5cfffcb8mreed *  None
21497903da2202008733f50e69997029d7a5cfffcb8mreed */
21597903da2202008733f50e69997029d7a5cfffcb8mreedvoid
21697903da2202008733f50e69997029d7a5cfffcb8mreedcalc_hd_mcastaddr(struct sockaddr_ll *lladdr_p, struct in6_addr *addr_p)
21797903da2202008733f50e69997029d7a5cfffcb8mreed{
21897903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_family    = AF_PACKET;	/* Always AF_PACKET */
21997903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_protocol  = htons(ETH_P_IPV6);	/* IPv6 */
22097903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_ifindex   = 0;		/* Unspecified here */
22197903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_hatype    = ARPHRD_ETHER;	/* Header type */
22297903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_pkttype   = PACKET_MULTICAST;	/* Packet type */
22397903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_halen	    = ETH_ALEN;		/* Length of address */
22497903da2202008733f50e69997029d7a5cfffcb8mreed
22597903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_addr[0]   = 0x33;
22697903da2202008733f50e69997029d7a5cfffcb8mreed    lladdr_p->sll_addr[1]   = 0x33;
22797903da2202008733f50e69997029d7a5cfffcb8mreed    memcpy(&lladdr_p->sll_addr[2], &addr_p->s6_addr[12], ETH_ALEN - 2);
22897903da2202008733f50e69997029d7a5cfffcb8mreed}
22997903da2202008733f50e69997029d7a5cfffcb8mreed
23097903da2202008733f50e69997029d7a5cfffcb8mreed/*
23197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: create_mld_query()
23297903da2202008733f50e69997029d7a5cfffcb8mreed *
23397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
23497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function create a mldv2 query information.
23597903da2202008733f50e69997029d7a5cfffcb8mreed *
23697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
23797903da2202008733f50e69997029d7a5cfffcb8mreed *  info_p:	pointer to data of icmp structure
23897903da2202008733f50e69997029d7a5cfffcb8mreed *   mrc:	Max Resp Code
23997903da2202008733f50e69997029d7a5cfffcb8mreed *   saddrs:	comma separated array of the source addresses
24097903da2202008733f50e69997029d7a5cfffcb8mreed *
24197903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
24297903da2202008733f50e69997029d7a5cfffcb8mreed *  0: Success
24397903da2202008733f50e69997029d7a5cfffcb8mreed *  1: Fail
24497903da2202008733f50e69997029d7a5cfffcb8mreed */
24597903da2202008733f50e69997029d7a5cfffcb8mreedint
24697903da2202008733f50e69997029d7a5cfffcb8mreedcreate_mld_query(struct icmp6_info *info_p, uint16_t mrc, char *saddrs)
24797903da2202008733f50e69997029d7a5cfffcb8mreed{
24897903da2202008733f50e69997029d7a5cfffcb8mreed    struct ip6_datagram pkt;		/* ICMPv6 packet */
24997903da2202008733f50e69997029d7a5cfffcb8mreed    struct hbh_router_alert *alart_p;	/* pointer to router alart */
25097903da2202008733f50e69997029d7a5cfffcb8mreed    struct my_mldv2_query *query_p;	/* pointer to my_mldv2_query */
25197903da2202008733f50e69997029d7a5cfffcb8mreed    struct pseudo_ip6_datagram pseudo;	/* ICMPv6 pseudo packet for checksum */
25297903da2202008733f50e69997029d7a5cfffcb8mreed    uint16_t numsrc;			/* number of source address */
25397903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned short int ip6_psize;	/* size of IPv6 payload */
25497903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned short int query_size;	/* size of my_mldv2_query */
25597903da2202008733f50e69997029d7a5cfffcb8mreed    struct in6_addr ip6;
25697903da2202008733f50e69997029d7a5cfffcb8mreed    uint32_t idx;
25797903da2202008733f50e69997029d7a5cfffcb8mreed    char *sp, *ep;
25897903da2202008733f50e69997029d7a5cfffcb8mreed
25997903da2202008733f50e69997029d7a5cfffcb8mreed    memset(&pkt, '\0', sizeof(struct ip6_datagram));
26097903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p = (struct hbh_router_alert *)&(pkt.payload);
26197903da2202008733f50e69997029d7a5cfffcb8mreed    query_p = (struct my_mldv2_query *)((unsigned char*)alart_p + sizeof(struct hbh_router_alert));
26297903da2202008733f50e69997029d7a5cfffcb8mreed
26397903da2202008733f50e69997029d7a5cfffcb8mreed    /* calculate the number of source address */
26497903da2202008733f50e69997029d7a5cfffcb8mreed    if (saddrs == NULL) {
26597903da2202008733f50e69997029d7a5cfffcb8mreed	numsrc = 0;
26697903da2202008733f50e69997029d7a5cfffcb8mreed    } else {
26797903da2202008733f50e69997029d7a5cfffcb8mreed	numsrc = 1;
26897903da2202008733f50e69997029d7a5cfffcb8mreed	for (sp = saddrs; *sp != '\0'; sp++)
26997903da2202008733f50e69997029d7a5cfffcb8mreed	    if (*sp == ',')
27097903da2202008733f50e69997029d7a5cfffcb8mreed		numsrc++;
27197903da2202008733f50e69997029d7a5cfffcb8mreed    }
27297903da2202008733f50e69997029d7a5cfffcb8mreed    if (debug)
27397903da2202008733f50e69997029d7a5cfffcb8mreed	fprintf(stderr, "number of source address is %u\n", numsrc);
27497903da2202008733f50e69997029d7a5cfffcb8mreed
27597903da2202008733f50e69997029d7a5cfffcb8mreed    query_size = MY_MLDV2_QUERY_SIZE(numsrc);
27697903da2202008733f50e69997029d7a5cfffcb8mreed    ip6_psize = sizeof(struct hbh_router_alert) + query_size;
27797903da2202008733f50e69997029d7a5cfffcb8mreed
27897903da2202008733f50e69997029d7a5cfffcb8mreed    /* IPv6 Header */
27997903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_vfc     = 6 << 4;
28097903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_flow    |= 0;
28197903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_plen    = htons(ip6_psize);
28297903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_nxt     = IPPROTO_HOPOPTS;
28397903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_hlim    = 1;
28497903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_src     = info_p->saddr;
28597903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_dst     = info_p->daddr;
28697903da2202008733f50e69997029d7a5cfffcb8mreed
28797903da2202008733f50e69997029d7a5cfffcb8mreed    /* Router Alert Option */
28897903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->nxthdr	= IPPROTO_ICMPV6;
28997903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->hbh_len	= 0;
29097903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->alart_type	= 0x05;			/* router alert */
29197903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->alart_len	= 0x02;			/* data len */
29297903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->alart_data	= htons(0x0000);	/* MLD */
29397903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->padn_type	= 0x01;			/* PadN option */
29497903da2202008733f50e69997029d7a5cfffcb8mreed    alart_p->padn_len	= 0x00;			/* 2 Octets */
29597903da2202008733f50e69997029d7a5cfffcb8mreed
29697903da2202008733f50e69997029d7a5cfffcb8mreed    /* MLDv2 query */
29797903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->type	= MLD_LISTENER_QUERY;
29897903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->code	= 0;
29997903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->cksum	= 0;			/* Calculate later */
30097903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->maxdelay	= htons(mrc);
30197903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->resv	= 0;
30297903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->suppress	= 0;
30397903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->qrv	= 0;
30497903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->qqic	= 0;
30597903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->nsrcs	= htons(numsrc);
30697903da2202008733f50e69997029d7a5cfffcb8mreed
30797903da2202008733f50e69997029d7a5cfffcb8mreed    /* define the multicast address */
30897903da2202008733f50e69997029d7a5cfffcb8mreed    if (memcmp(&info_p->daddr, &in6addr_allnodes, sizeof(struct in6_addr)) == 0)
30997903da2202008733f50e69997029d7a5cfffcb8mreed	query_p->addr	= in6addr_any;
31097903da2202008733f50e69997029d7a5cfffcb8mreed    else
31197903da2202008733f50e69997029d7a5cfffcb8mreed	query_p->addr	= info_p->daddr;
31297903da2202008733f50e69997029d7a5cfffcb8mreed
31397903da2202008733f50e69997029d7a5cfffcb8mreed    /* substitute source addresses */
31497903da2202008733f50e69997029d7a5cfffcb8mreed    sp = saddrs;
315df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper    for (idx = 0; idx < numsrc; idx++) {
31697903da2202008733f50e69997029d7a5cfffcb8mreed	ep = strchr(sp, ',');
31797903da2202008733f50e69997029d7a5cfffcb8mreed	if (ep != NULL)
31897903da2202008733f50e69997029d7a5cfffcb8mreed	    *ep = '\0';
31997903da2202008733f50e69997029d7a5cfffcb8mreed	if (debug)
32097903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "source address[%u]: %s\n", idx, sp);
32197903da2202008733f50e69997029d7a5cfffcb8mreed
32297903da2202008733f50e69997029d7a5cfffcb8mreed	if (inet_pton(AF_INET6, sp, &ip6) <= 0) {
32397903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "source address list is something wrong\n");
32497903da2202008733f50e69997029d7a5cfffcb8mreed	    return 1;
32597903da2202008733f50e69997029d7a5cfffcb8mreed	}
32697903da2202008733f50e69997029d7a5cfffcb8mreed	query_p->srcs[idx] = ip6;
32797903da2202008733f50e69997029d7a5cfffcb8mreed	sp = ep + 1;
32897903da2202008733f50e69997029d7a5cfffcb8mreed    }
32997903da2202008733f50e69997029d7a5cfffcb8mreed
33097903da2202008733f50e69997029d7a5cfffcb8mreed    /* ICMPv6 Pseudo packet */
33197903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_src	= pkt.hdr.ip6_src;
33297903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_dst	= pkt.hdr.ip6_dst;
33397903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_plen	= htons(query_size);
33497903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_zero1	= 0;
33597903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_zero2	= 0;
33697903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_nxt	= IPPROTO_ICMPV6;
33797903da2202008733f50e69997029d7a5cfffcb8mreed    memcpy(pseudo.payload, query_p, query_size);
33897903da2202008733f50e69997029d7a5cfffcb8mreed
33997903da2202008733f50e69997029d7a5cfffcb8mreed    /* Calcualte checksums */
34097903da2202008733f50e69997029d7a5cfffcb8mreed    query_p->cksum = calc_checksum((u_int16_t *)(&pseudo),
34197903da2202008733f50e69997029d7a5cfffcb8mreed	    sizeof(struct pseudo_ip6_hdr) + query_size);
34297903da2202008733f50e69997029d7a5cfffcb8mreed
34397903da2202008733f50e69997029d7a5cfffcb8mreed    /* Store the clean packet data */
34497903da2202008733f50e69997029d7a5cfffcb8mreed    info_p->pkt = pkt;
34597903da2202008733f50e69997029d7a5cfffcb8mreed    info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize;
34697903da2202008733f50e69997029d7a5cfffcb8mreed
3477d0a4a57fbcd47f72b67c08df532e8ef47f6fdaeGarrett Cooper        return 0;
34897903da2202008733f50e69997029d7a5cfffcb8mreed}
34997903da2202008733f50e69997029d7a5cfffcb8mreed
35097903da2202008733f50e69997029d7a5cfffcb8mreed/*
35197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: create_echo_request()
35297903da2202008733f50e69997029d7a5cfffcb8mreed *
35397903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
35497903da2202008733f50e69997029d7a5cfffcb8mreed *  This function creates icmpv6 echo request
35597903da2202008733f50e69997029d7a5cfffcb8mreed *
35697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
35797903da2202008733f50e69997029d7a5cfffcb8mreed *  info_p: pointer to data of icmp structure
35897903da2202008733f50e69997029d7a5cfffcb8mreed *
35997903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
36097903da2202008733f50e69997029d7a5cfffcb8mreed *  None
36197903da2202008733f50e69997029d7a5cfffcb8mreed */
36297903da2202008733f50e69997029d7a5cfffcb8mreedvoid
36397903da2202008733f50e69997029d7a5cfffcb8mreedcreate_echo_request(struct icmp6_info *info_p)
36497903da2202008733f50e69997029d7a5cfffcb8mreed{
36597903da2202008733f50e69997029d7a5cfffcb8mreed    struct ip6_datagram pkt;		/* ICMPv6 packet */
36697903da2202008733f50e69997029d7a5cfffcb8mreed    struct icmp6_segment *echoreq_p;	/* Echo request header and payload */
36797903da2202008733f50e69997029d7a5cfffcb8mreed    struct pseudo_ip6_datagram pseudo;	/* ICMPv6 pseudo packet for checksum */
36897903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned short int ip6_psize;	/* payload size */
36997903da2202008733f50e69997029d7a5cfffcb8mreed
37097903da2202008733f50e69997029d7a5cfffcb8mreed    ip6_psize = sizeof(struct icmp6_hdr)	/* ICMP header */
37197903da2202008733f50e69997029d7a5cfffcb8mreed		    + info_p->data_size;	/* ICMP payload */
37297903da2202008733f50e69997029d7a5cfffcb8mreed    memset(&pkt, '\0', sizeof(struct ip6_datagram));
37397903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p = (struct icmp6_segment *)&(pkt.payload);
37497903da2202008733f50e69997029d7a5cfffcb8mreed
37597903da2202008733f50e69997029d7a5cfffcb8mreed    /* IPv6 Header */
37697903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_vfc	= 6 << 4;
37797903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_flow	|= 0;
37897903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_plen	= htons(ip6_psize);
37997903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_nxt	= IPPROTO_ICMPV6;
38097903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_hlim	= IPV6_DEFAULT_HOPLIMIT;
38197903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_src	= info_p->saddr;
38297903da2202008733f50e69997029d7a5cfffcb8mreed    pkt.hdr.ip6_dst	= info_p->daddr;
38397903da2202008733f50e69997029d7a5cfffcb8mreed
38497903da2202008733f50e69997029d7a5cfffcb8mreed    /* Echo Request Header */
38597903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_type	= ICMP6_ECHO_REQUEST;
38697903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_code	= 0;
38797903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_cksum	= 0;	/* Calculate later */
38897903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_id		= htons(ICMP_ECHO_ID);
38997903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_seq		= htons(1);
39097903da2202008733f50e69997029d7a5cfffcb8mreed
39197903da2202008733f50e69997029d7a5cfffcb8mreed    /* Echo Request Payload */
39297903da2202008733f50e69997029d7a5cfffcb8mreed    fill_payload(echoreq_p->data, info_p->data_size);
39397903da2202008733f50e69997029d7a5cfffcb8mreed
39497903da2202008733f50e69997029d7a5cfffcb8mreed    /* ICMPv6 Pseudo packet */
39597903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_src	= pkt.hdr.ip6_src;
39697903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_dst	= pkt.hdr.ip6_dst;
39797903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_plen	= htons(ip6_psize);
39897903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_zero1	= 0;
39997903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_zero2	= 0;
40097903da2202008733f50e69997029d7a5cfffcb8mreed    pseudo.hdr.p_ip6_nxt	= IPPROTO_ICMPV6;
40197903da2202008733f50e69997029d7a5cfffcb8mreed    memcpy(pseudo.payload, echoreq_p, ip6_psize);
40297903da2202008733f50e69997029d7a5cfffcb8mreed
40397903da2202008733f50e69997029d7a5cfffcb8mreed    /* Calcualte checksums */
40497903da2202008733f50e69997029d7a5cfffcb8mreed    echoreq_p->hdr.icmp6_cksum = calc_checksum((u_int16_t *)(&pseudo),
40597903da2202008733f50e69997029d7a5cfffcb8mreed				sizeof(struct pseudo_ip6_hdr) + ip6_psize);
40697903da2202008733f50e69997029d7a5cfffcb8mreed
40797903da2202008733f50e69997029d7a5cfffcb8mreed    /* Store the clean packet data */
40897903da2202008733f50e69997029d7a5cfffcb8mreed    info_p->pkt = pkt;
40997903da2202008733f50e69997029d7a5cfffcb8mreed    info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize;
41097903da2202008733f50e69997029d7a5cfffcb8mreed}
41197903da2202008733f50e69997029d7a5cfffcb8mreed
41297903da2202008733f50e69997029d7a5cfffcb8mreed/*
41397903da2202008733f50e69997029d7a5cfffcb8mreed * Function: parse_options()
41497903da2202008733f50e69997029d7a5cfffcb8mreed *
41597903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
41697903da2202008733f50e69997029d7a5cfffcb8mreed *  This function parse the options
41797903da2202008733f50e69997029d7a5cfffcb8mreed *
41897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
41997903da2202008733f50e69997029d7a5cfffcb8mreed *   argc:  the number of argument
42097903da2202008733f50e69997029d7a5cfffcb8mreed *   argv:  arguments
42197903da2202008733f50e69997029d7a5cfffcb8mreed *  info_p: pointer to data of icmp data to modify
42297903da2202008733f50e69997029d7a5cfffcb8mreed *   bg_p:  pointer to the flag of working in backgrond
42397903da2202008733f50e69997029d7a5cfffcb8mreed *
42497903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
42597903da2202008733f50e69997029d7a5cfffcb8mreed *  None
42697903da2202008733f50e69997029d7a5cfffcb8mreed */
42797903da2202008733f50e69997029d7a5cfffcb8mreedvoid
42897903da2202008733f50e69997029d7a5cfffcb8mreedparse_options(int argc, char *argv[], struct icmp6_info *info_p, int *bg_p)
42997903da2202008733f50e69997029d7a5cfffcb8mreed{
43097903da2202008733f50e69997029d7a5cfffcb8mreed    int optc;			/* option */
43197903da2202008733f50e69997029d7a5cfffcb8mreed    unsigned long opt_ul;	/* option value in unsigned long */
43297903da2202008733f50e69997029d7a5cfffcb8mreed    double opt_d;		/* option value in double */
43397903da2202008733f50e69997029d7a5cfffcb8mreed    struct in6_addr opt_addr;	/* option value in struct in_addr */
43497903da2202008733f50e69997029d7a5cfffcb8mreed    struct sockaddr_ll opt_addr_ll;	/* option value in struct sockaddr_ll */
43597903da2202008733f50e69997029d7a5cfffcb8mreed    char *ifname;		/* interface name where datagrams go out */
43697903da2202008733f50e69997029d7a5cfffcb8mreed    int  is_mld_query;		/* set to non-zero if sending MLDv2 query */
43797903da2202008733f50e69997029d7a5cfffcb8mreed    char *mld_saddrs;		/* comma separated array of source addresses */
43897903da2202008733f50e69997029d7a5cfffcb8mreed    uint16_t max_resp;		/* Max Resp Code */
43997903da2202008733f50e69997029d7a5cfffcb8mreed    int is_specified_daddr_ll = 0;
44097903da2202008733f50e69997029d7a5cfffcb8mreed    int is_specified_saddr = 0;
44197903da2202008733f50e69997029d7a5cfffcb8mreed    int is_specified_daddr = 0;
44297903da2202008733f50e69997029d7a5cfffcb8mreed
44397903da2202008733f50e69997029d7a5cfffcb8mreed    ifname = NULL;
44497903da2202008733f50e69997029d7a5cfffcb8mreed    is_mld_query = 0;
44597903da2202008733f50e69997029d7a5cfffcb8mreed    mld_saddrs = NULL;
44697903da2202008733f50e69997029d7a5cfffcb8mreed    max_resp = MY_MLD_MAX_HOST_REPORT_DELAY;
44797903da2202008733f50e69997029d7a5cfffcb8mreed
4488fb1cdb0538640f295691929650408688537fb7fGarrett Cooper    while ((optc = getopt(argc, argv, "I:S:M:D:t:w:obdhs:iLnvma:r:")) != EOF) {
44997903da2202008733f50e69997029d7a5cfffcb8mreed	switch (optc) {
45097903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'I':
451df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper		if (if_nametoindex(optarg) == 0) {
45297903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "specified interface is incorrect\n");
45397903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
45497903da2202008733f50e69997029d7a5cfffcb8mreed		}
45597903da2202008733f50e69997029d7a5cfffcb8mreed		ifname = strdup(optarg);
45697903da2202008733f50e69997029d7a5cfffcb8mreed		if (ifname == NULL)
45797903da2202008733f50e69997029d7a5cfffcb8mreed		    fatal_error("strdup() failed.");
45897903da2202008733f50e69997029d7a5cfffcb8mreed		break;
45997903da2202008733f50e69997029d7a5cfffcb8mreed
46097903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'S':
46197903da2202008733f50e69997029d7a5cfffcb8mreed		if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) {
46297903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Source address is wrong\n");
46397903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
46497903da2202008733f50e69997029d7a5cfffcb8mreed		}
46597903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->saddr = opt_addr;
46697903da2202008733f50e69997029d7a5cfffcb8mreed		is_specified_saddr = 1;
46797903da2202008733f50e69997029d7a5cfffcb8mreed		break;
46897903da2202008733f50e69997029d7a5cfffcb8mreed
46997903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'M':
47097903da2202008733f50e69997029d7a5cfffcb8mreed		if (eth_pton(AF_INET6, optarg, &opt_addr_ll)) {
47197903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Destination MAC address is wrong\n");
47297903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
47397903da2202008733f50e69997029d7a5cfffcb8mreed		}
47497903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->daddr_ll = opt_addr_ll;
47597903da2202008733f50e69997029d7a5cfffcb8mreed		is_specified_daddr_ll = 1;
47697903da2202008733f50e69997029d7a5cfffcb8mreed		break;
47797903da2202008733f50e69997029d7a5cfffcb8mreed
47897903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'D':
47997903da2202008733f50e69997029d7a5cfffcb8mreed		if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) {
48097903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Destination address is wrong\n");
48197903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
48297903da2202008733f50e69997029d7a5cfffcb8mreed		}
48397903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->daddr = opt_addr;
48497903da2202008733f50e69997029d7a5cfffcb8mreed		is_specified_daddr = 1;
48597903da2202008733f50e69997029d7a5cfffcb8mreed		break;
48697903da2202008733f50e69997029d7a5cfffcb8mreed
48797903da2202008733f50e69997029d7a5cfffcb8mreed	    case 't':
48897903da2202008733f50e69997029d7a5cfffcb8mreed		opt_d = strtod(optarg, NULL);
48997903da2202008733f50e69997029d7a5cfffcb8mreed		if (opt_d < 0.0) {
49097903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Timeout should be positive value\n");
49197903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
49297903da2202008733f50e69997029d7a5cfffcb8mreed		}
49397903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->timeout = opt_d;
49497903da2202008733f50e69997029d7a5cfffcb8mreed		break;
49597903da2202008733f50e69997029d7a5cfffcb8mreed
49697903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'w':
49797903da2202008733f50e69997029d7a5cfffcb8mreed		if (strtotimespec(optarg, &info_p->interval)) {
49897903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Interval is something wrong\n");
49997903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
50097903da2202008733f50e69997029d7a5cfffcb8mreed		}
50197903da2202008733f50e69997029d7a5cfffcb8mreed		break;
50297903da2202008733f50e69997029d7a5cfffcb8mreed
50397903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'o':
50497903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->timeout = -1.0;
50597903da2202008733f50e69997029d7a5cfffcb8mreed		break;
50697903da2202008733f50e69997029d7a5cfffcb8mreed
50797903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'b':
50897903da2202008733f50e69997029d7a5cfffcb8mreed		*bg_p = 1;
50997903da2202008733f50e69997029d7a5cfffcb8mreed		break;
51097903da2202008733f50e69997029d7a5cfffcb8mreed
51197903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'd':
51297903da2202008733f50e69997029d7a5cfffcb8mreed		debug = 1;
51397903da2202008733f50e69997029d7a5cfffcb8mreed		break;
51497903da2202008733f50e69997029d7a5cfffcb8mreed
51597903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'h':
51697903da2202008733f50e69997029d7a5cfffcb8mreed		usage(program_name, EXIT_SUCCESS);
51797903da2202008733f50e69997029d7a5cfffcb8mreed		break;
51897903da2202008733f50e69997029d7a5cfffcb8mreed
51997903da2202008733f50e69997029d7a5cfffcb8mreed	    /* Options for echo request */
52097903da2202008733f50e69997029d7a5cfffcb8mreed	    case 's':
52197903da2202008733f50e69997029d7a5cfffcb8mreed		opt_ul = strtoul(optarg, NULL, 0);
52297903da2202008733f50e69997029d7a5cfffcb8mreed		if (opt_ul > ICMPV6_DATA_MAXSIZE) {
52397903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Data size sholud be less than %d\n", ICMPV6_DATA_MAXSIZE + 1);
52497903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
52597903da2202008733f50e69997029d7a5cfffcb8mreed		}
52697903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->data_size = opt_ul;
52797903da2202008733f50e69997029d7a5cfffcb8mreed		break;
52897903da2202008733f50e69997029d7a5cfffcb8mreed
52997903da2202008733f50e69997029d7a5cfffcb8mreed	    /* Options for fake */
53097903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'i':
53197903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->fake_flag |= FAKE_DADDR;
53297903da2202008733f50e69997029d7a5cfffcb8mreed		break;
53397903da2202008733f50e69997029d7a5cfffcb8mreed
53497903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'L':
53597903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->fake_flag |= FAKE_PLEN;
53697903da2202008733f50e69997029d7a5cfffcb8mreed		break;
53797903da2202008733f50e69997029d7a5cfffcb8mreed
53897903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'n':
53997903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->fake_flag |= FAKE_NXT;
54097903da2202008733f50e69997029d7a5cfffcb8mreed		break;
54197903da2202008733f50e69997029d7a5cfffcb8mreed
54297903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'v':
54397903da2202008733f50e69997029d7a5cfffcb8mreed		info_p->fake_flag |= FAKE_VERSION;
54497903da2202008733f50e69997029d7a5cfffcb8mreed		break;
54597903da2202008733f50e69997029d7a5cfffcb8mreed
54697903da2202008733f50e69997029d7a5cfffcb8mreed	    /* Options for MLDv2 query */
54797903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'm':
54897903da2202008733f50e69997029d7a5cfffcb8mreed		is_mld_query = 1;
54997903da2202008733f50e69997029d7a5cfffcb8mreed		break;
55097903da2202008733f50e69997029d7a5cfffcb8mreed
55197903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'a':
55297903da2202008733f50e69997029d7a5cfffcb8mreed		mld_saddrs = strdup(optarg);
55397903da2202008733f50e69997029d7a5cfffcb8mreed		if (mld_saddrs == NULL)
55497903da2202008733f50e69997029d7a5cfffcb8mreed		    fatal_error("strdup()");
55597903da2202008733f50e69997029d7a5cfffcb8mreed		break;
55697903da2202008733f50e69997029d7a5cfffcb8mreed
55797903da2202008733f50e69997029d7a5cfffcb8mreed	    case 'r':
55897903da2202008733f50e69997029d7a5cfffcb8mreed		opt_ul=strtoul(optarg, NULL, 0);
55997903da2202008733f50e69997029d7a5cfffcb8mreed		if (opt_ul > 0xFFFF) {
56097903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Max Resp Code should be less than 65536\n");
56197903da2202008733f50e69997029d7a5cfffcb8mreed		    usage(program_name, EXIT_FAILURE);
56297903da2202008733f50e69997029d7a5cfffcb8mreed		}
56397903da2202008733f50e69997029d7a5cfffcb8mreed		max_resp = opt_ul;
56497903da2202008733f50e69997029d7a5cfffcb8mreed		break;
56597903da2202008733f50e69997029d7a5cfffcb8mreed
56697903da2202008733f50e69997029d7a5cfffcb8mreed	    default:
56797903da2202008733f50e69997029d7a5cfffcb8mreed		usage(program_name, EXIT_FAILURE);
56897903da2202008733f50e69997029d7a5cfffcb8mreed	}
56997903da2202008733f50e69997029d7a5cfffcb8mreed    }
57097903da2202008733f50e69997029d7a5cfffcb8mreed
57197903da2202008733f50e69997029d7a5cfffcb8mreed    if (ifname == NULL) {
57297903da2202008733f50e69997029d7a5cfffcb8mreed	fprintf(stderr, "Outgoing interface is not specified\n");
57397903da2202008733f50e69997029d7a5cfffcb8mreed	usage(program_name, EXIT_FAILURE);
57497903da2202008733f50e69997029d7a5cfffcb8mreed    }
57597903da2202008733f50e69997029d7a5cfffcb8mreed    specify_hw_addr(&info_p->saddr_ll, ifname);
57697903da2202008733f50e69997029d7a5cfffcb8mreed
57797903da2202008733f50e69997029d7a5cfffcb8mreed    if (! is_specified_saddr) {
57897903da2202008733f50e69997029d7a5cfffcb8mreed	fprintf(stderr, "Source IP address is not specified\n");
57997903da2202008733f50e69997029d7a5cfffcb8mreed	usage(program_name, EXIT_FAILURE);
58097903da2202008733f50e69997029d7a5cfffcb8mreed    }
58197903da2202008733f50e69997029d7a5cfffcb8mreed
58297903da2202008733f50e69997029d7a5cfffcb8mreed    if (is_mld_query) {		/* MLDv2 query */
58397903da2202008733f50e69997029d7a5cfffcb8mreed	if (info_p->fake_flag) {
58497903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "It is not permitted to break MLDv2 query\n");
58597903da2202008733f50e69997029d7a5cfffcb8mreed	    usage(program_name, EXIT_FAILURE);
58697903da2202008733f50e69997029d7a5cfffcb8mreed	}
58797903da2202008733f50e69997029d7a5cfffcb8mreed
58897903da2202008733f50e69997029d7a5cfffcb8mreed	if (! is_specified_daddr)
58997903da2202008733f50e69997029d7a5cfffcb8mreed	    info_p->daddr = in6addr_allnodes;
59097903da2202008733f50e69997029d7a5cfffcb8mreed
59197903da2202008733f50e69997029d7a5cfffcb8mreed	calc_hd_mcastaddr(&info_p->daddr_ll, &info_p->daddr);
59297903da2202008733f50e69997029d7a5cfffcb8mreed	if (create_mld_query(info_p, max_resp, mld_saddrs))
59397903da2202008733f50e69997029d7a5cfffcb8mreed	    exit(EXIT_FAILURE);
59497903da2202008733f50e69997029d7a5cfffcb8mreed    } else {			/* echo request */
59597903da2202008733f50e69997029d7a5cfffcb8mreed	if (info_p->fake_flag)
59697903da2202008733f50e69997029d7a5cfffcb8mreed	    srand(getpid());
59797903da2202008733f50e69997029d7a5cfffcb8mreed
59897903da2202008733f50e69997029d7a5cfffcb8mreed	if (! is_specified_daddr_ll) {
59997903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "Destination MAC address is not specified\n");
60097903da2202008733f50e69997029d7a5cfffcb8mreed	    usage(program_name, EXIT_FAILURE);
60197903da2202008733f50e69997029d7a5cfffcb8mreed	}
60297903da2202008733f50e69997029d7a5cfffcb8mreed
60397903da2202008733f50e69997029d7a5cfffcb8mreed	if (! is_specified_daddr) {
60497903da2202008733f50e69997029d7a5cfffcb8mreed	    fprintf(stderr, "Destination IP address is not specified\n");
60597903da2202008733f50e69997029d7a5cfffcb8mreed	    usage(program_name, EXIT_FAILURE);
60697903da2202008733f50e69997029d7a5cfffcb8mreed	}
60797903da2202008733f50e69997029d7a5cfffcb8mreed
60897903da2202008733f50e69997029d7a5cfffcb8mreed	create_echo_request(info_p);
60997903da2202008733f50e69997029d7a5cfffcb8mreed    }
61097903da2202008733f50e69997029d7a5cfffcb8mreed    info_p->daddr_ll.sll_ifindex = if_nametoindex(ifname);
61197903da2202008733f50e69997029d7a5cfffcb8mreed}
61297903da2202008733f50e69997029d7a5cfffcb8mreed
61397903da2202008733f50e69997029d7a5cfffcb8mreed/*
61497903da2202008733f50e69997029d7a5cfffcb8mreed * Function: thrust_fakes()
61597903da2202008733f50e69997029d7a5cfffcb8mreed *
61697903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
61797903da2202008733f50e69997029d7a5cfffcb8mreed *  This function thrust fake information to the icmp packet
61897903da2202008733f50e69997029d7a5cfffcb8mreed *
61997903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
62097903da2202008733f50e69997029d7a5cfffcb8mreed *     pkt   : Payload of the Ethernet frame (Namely, IPv6 packet)
62197903da2202008733f50e69997029d7a5cfffcb8mreed *  fake_flag: Flag which represents what information would be faked
62297903da2202008733f50e69997029d7a5cfffcb8mreed *
62397903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
62497903da2202008733f50e69997029d7a5cfffcb8mreed *  None
62597903da2202008733f50e69997029d7a5cfffcb8mreed */
62697903da2202008733f50e69997029d7a5cfffcb8mreedvoid
62797903da2202008733f50e69997029d7a5cfffcb8mreedthrust_fakes(struct ip6_datagram *pkt, u_int16_t fake_flag)
62897903da2202008733f50e69997029d7a5cfffcb8mreed{
62997903da2202008733f50e69997029d7a5cfffcb8mreed    int rand_val;
63097903da2202008733f50e69997029d7a5cfffcb8mreed    size_t bitsize;
63197903da2202008733f50e69997029d7a5cfffcb8mreed    u_int32_t seed;
63297903da2202008733f50e69997029d7a5cfffcb8mreed
63397903da2202008733f50e69997029d7a5cfffcb8mreed    if (debug)
63497903da2202008733f50e69997029d7a5cfffcb8mreed	fprintf(stderr, "fake_flag = %2x\n", fake_flag);
63597903da2202008733f50e69997029d7a5cfffcb8mreed
63697903da2202008733f50e69997029d7a5cfffcb8mreed    if (fake_flag & FAKE_VERSION) {	/* version */
63797903da2202008733f50e69997029d7a5cfffcb8mreed	bitsize = 4;
63897903da2202008733f50e69997029d7a5cfffcb8mreed	seed = bit_change_seed(bitsize, 1);
63997903da2202008733f50e69997029d7a5cfffcb8mreed	pkt->hdr.ip6_vfc ^= (seed << 4);
64097903da2202008733f50e69997029d7a5cfffcb8mreed    }
64197903da2202008733f50e69997029d7a5cfffcb8mreed
64297903da2202008733f50e69997029d7a5cfffcb8mreed    if (fake_flag & FAKE_PLEN) {	/* total length */
64397903da2202008733f50e69997029d7a5cfffcb8mreed	bitsize = sizeof(pkt->hdr.ip6_plen) * 8;
64497903da2202008733f50e69997029d7a5cfffcb8mreed	seed = bit_change_seed(bitsize, bitsize / 8);
64597903da2202008733f50e69997029d7a5cfffcb8mreed	pkt->hdr.ip6_plen ^= seed;
64697903da2202008733f50e69997029d7a5cfffcb8mreed    }
64797903da2202008733f50e69997029d7a5cfffcb8mreed
64897903da2202008733f50e69997029d7a5cfffcb8mreed    if (fake_flag & FAKE_NXT) {		/* next header */
64997903da2202008733f50e69997029d7a5cfffcb8mreed	rand_val = rand() / ((RAND_MAX + 1U) / 5);
65097903da2202008733f50e69997029d7a5cfffcb8mreed	switch (rand_val) {
65197903da2202008733f50e69997029d7a5cfffcb8mreed	    case 1:
65297903da2202008733f50e69997029d7a5cfffcb8mreed	    case 2:
65397903da2202008733f50e69997029d7a5cfffcb8mreed		if (debug)
65497903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Bit reverse\n");
65597903da2202008733f50e69997029d7a5cfffcb8mreed		bitsize = sizeof(pkt->hdr.ip6_nxt) * 8;
65697903da2202008733f50e69997029d7a5cfffcb8mreed		seed = bit_change_seed(bitsize, 0);
65797903da2202008733f50e69997029d7a5cfffcb8mreed		pkt->hdr.ip6_nxt ^= seed;
65897903da2202008733f50e69997029d7a5cfffcb8mreed		break;
65997903da2202008733f50e69997029d7a5cfffcb8mreed
66097903da2202008733f50e69997029d7a5cfffcb8mreed	    case 3:
66197903da2202008733f50e69997029d7a5cfffcb8mreed	    case 4:
66297903da2202008733f50e69997029d7a5cfffcb8mreed		if (debug)
66397903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Unknown Protocol\n");
66497903da2202008733f50e69997029d7a5cfffcb8mreed		if (rand_val) {
66597903da2202008733f50e69997029d7a5cfffcb8mreed		    int number;
66697903da2202008733f50e69997029d7a5cfffcb8mreed		    int counter;
667df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper		    for (counter=0; counter <= 0xff; counter++) {
66897903da2202008733f50e69997029d7a5cfffcb8mreed			number = rand() / ((RAND_MAX + 1U) / 0x100);
66997903da2202008733f50e69997029d7a5cfffcb8mreed			if (getprotobynumber(number) == NULL) {
67097903da2202008733f50e69997029d7a5cfffcb8mreed			    pkt->hdr.ip6_nxt = number;
67197903da2202008733f50e69997029d7a5cfffcb8mreed			    break;
67297903da2202008733f50e69997029d7a5cfffcb8mreed			}
67397903da2202008733f50e69997029d7a5cfffcb8mreed		    }
67497903da2202008733f50e69997029d7a5cfffcb8mreed		}
67597903da2202008733f50e69997029d7a5cfffcb8mreed		break;
67697903da2202008733f50e69997029d7a5cfffcb8mreed
67797903da2202008733f50e69997029d7a5cfffcb8mreed	    default:
67897903da2202008733f50e69997029d7a5cfffcb8mreed		if (debug)
67997903da2202008733f50e69997029d7a5cfffcb8mreed		    fprintf(stderr, "Do nothing\n");
68097903da2202008733f50e69997029d7a5cfffcb8mreed		break;
68197903da2202008733f50e69997029d7a5cfffcb8mreed	}
68297903da2202008733f50e69997029d7a5cfffcb8mreed    }
68397903da2202008733f50e69997029d7a5cfffcb8mreed
68497903da2202008733f50e69997029d7a5cfffcb8mreed    if (fake_flag & FAKE_DADDR) {	/* destination address */
68597903da2202008733f50e69997029d7a5cfffcb8mreed	rand_val = rand() / ((RAND_MAX + 1U) / 4);
68697903da2202008733f50e69997029d7a5cfffcb8mreed	bitsize = sizeof(pkt->hdr.ip6_dst.s6_addr32[rand_val]) * 8;
68797903da2202008733f50e69997029d7a5cfffcb8mreed	seed = bit_change_seed(bitsize, bitsize / 8);
68897903da2202008733f50e69997029d7a5cfffcb8mreed	pkt->hdr.ip6_dst.s6_addr32[rand_val] ^= seed;
68997903da2202008733f50e69997029d7a5cfffcb8mreed    }
69097903da2202008733f50e69997029d7a5cfffcb8mreed}
69197903da2202008733f50e69997029d7a5cfffcb8mreed
69297903da2202008733f50e69997029d7a5cfffcb8mreed/*
69397903da2202008733f50e69997029d7a5cfffcb8mreed * Function: send_packet()
69497903da2202008733f50e69997029d7a5cfffcb8mreed *
69597903da2202008733f50e69997029d7a5cfffcb8mreed * Description:
69697903da2202008733f50e69997029d7a5cfffcb8mreed *  This function sends icmpv6 packet
69797903da2202008733f50e69997029d7a5cfffcb8mreed *
69897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument:
69997903da2202008733f50e69997029d7a5cfffcb8mreed *  info_p: pointer to data of icmp structure
70097903da2202008733f50e69997029d7a5cfffcb8mreed *
70197903da2202008733f50e69997029d7a5cfffcb8mreed * Return value:
70297903da2202008733f50e69997029d7a5cfffcb8mreed *  None
70397903da2202008733f50e69997029d7a5cfffcb8mreed */
70497903da2202008733f50e69997029d7a5cfffcb8mreedvoid
70597903da2202008733f50e69997029d7a5cfffcb8mreedsend_packets(struct icmp6_info *info_p)
70697903da2202008733f50e69997029d7a5cfffcb8mreed{
70797903da2202008733f50e69997029d7a5cfffcb8mreed    int sock_fd;
70897903da2202008733f50e69997029d7a5cfffcb8mreed    int retval;
70997903da2202008733f50e69997029d7a5cfffcb8mreed    struct ip6_datagram pkt;
71097903da2202008733f50e69997029d7a5cfffcb8mreed    double start_time;
71197903da2202008733f50e69997029d7a5cfffcb8mreed
71297903da2202008733f50e69997029d7a5cfffcb8mreed    /* Open a socket */
71397903da2202008733f50e69997029d7a5cfffcb8mreed    sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6));
71497903da2202008733f50e69997029d7a5cfffcb8mreed    if (sock_fd < 0)
71597903da2202008733f50e69997029d7a5cfffcb8mreed	fatal_error("socket()");
71697903da2202008733f50e69997029d7a5cfffcb8mreed
71797903da2202008733f50e69997029d7a5cfffcb8mreed    /* Bind the socket to the physical address */
71897903da2202008733f50e69997029d7a5cfffcb8mreed    retval = bind(sock_fd, (struct sockaddr *)&(info_p->saddr_ll),
71997903da2202008733f50e69997029d7a5cfffcb8mreed			sizeof(struct sockaddr_ll));
72097903da2202008733f50e69997029d7a5cfffcb8mreed    if (retval < 0)
72197903da2202008733f50e69997029d7a5cfffcb8mreed	fatal_error("bind()");
72297903da2202008733f50e69997029d7a5cfffcb8mreed
72397903da2202008733f50e69997029d7a5cfffcb8mreed    /* Set singal hander for SIGHUP */
72497903da2202008733f50e69997029d7a5cfffcb8mreed    handler.sa_handler = set_signal_flag;
72597903da2202008733f50e69997029d7a5cfffcb8mreed    handler.sa_flags = 0;
72697903da2202008733f50e69997029d7a5cfffcb8mreed    if (sigfillset(&handler.sa_mask) < 0)
72797903da2202008733f50e69997029d7a5cfffcb8mreed	fatal_error("sigfillset()");
72897903da2202008733f50e69997029d7a5cfffcb8mreed    if (sigaction(SIGHUP, &handler, NULL) < 0)
72997903da2202008733f50e69997029d7a5cfffcb8mreed	fatal_error("sigfillset()");
73097903da2202008733f50e69997029d7a5cfffcb8mreed
73197903da2202008733f50e69997029d7a5cfffcb8mreed    /*
73297903da2202008733f50e69997029d7a5cfffcb8mreed     * loop for sending packets
73397903da2202008733f50e69997029d7a5cfffcb8mreed     */
73497903da2202008733f50e69997029d7a5cfffcb8mreed    pkt	= info_p->pkt;
73597903da2202008733f50e69997029d7a5cfffcb8mreed    start_time = time(NULL);
73697903da2202008733f50e69997029d7a5cfffcb8mreed
737df3eb16e38c6a163b0a7367c885679eed6140964Garrett Cooper    for (;;) {
73897903da2202008733f50e69997029d7a5cfffcb8mreed	if (info_p->fake_flag) {
73997903da2202008733f50e69997029d7a5cfffcb8mreed	    pkt	= info_p->pkt;
74097903da2202008733f50e69997029d7a5cfffcb8mreed	    thrust_fakes(&pkt, info_p->fake_flag);
74197903da2202008733f50e69997029d7a5cfffcb8mreed	}
74297903da2202008733f50e69997029d7a5cfffcb8mreed
74397903da2202008733f50e69997029d7a5cfffcb8mreed	retval = sendto(sock_fd, &pkt, info_p->pkt_size, 0,
74497903da2202008733f50e69997029d7a5cfffcb8mreed		(struct sockaddr *)&(info_p->daddr_ll),
74597903da2202008733f50e69997029d7a5cfffcb8mreed		sizeof(struct sockaddr_ll));
74697903da2202008733f50e69997029d7a5cfffcb8mreed	if (retval < 0)
74797903da2202008733f50e69997029d7a5cfffcb8mreed	    fatal_error("sendto()");
74897903da2202008733f50e69997029d7a5cfffcb8mreed
74997903da2202008733f50e69997029d7a5cfffcb8mreed	/* Check timeout:
75097903da2202008733f50e69997029d7a5cfffcb8mreed	   If timeout value is negative only send one datagram */
75197903da2202008733f50e69997029d7a5cfffcb8mreed	if (info_p->timeout)
75297903da2202008733f50e69997029d7a5cfffcb8mreed	    if (info_p->timeout < difftime(time(NULL), start_time))
75397903da2202008733f50e69997029d7a5cfffcb8mreed		break;
75497903da2202008733f50e69997029d7a5cfffcb8mreed
75597903da2202008733f50e69997029d7a5cfffcb8mreed	/* Wait in specified interval */
75697903da2202008733f50e69997029d7a5cfffcb8mreed	nanosleep(&info_p->interval, NULL);
75797903da2202008733f50e69997029d7a5cfffcb8mreed
75897903da2202008733f50e69997029d7a5cfffcb8mreed	if (catch_sighup) /* catch SIGHUP */
75997903da2202008733f50e69997029d7a5cfffcb8mreed	    break;
76097903da2202008733f50e69997029d7a5cfffcb8mreed    }
76197903da2202008733f50e69997029d7a5cfffcb8mreed
76297903da2202008733f50e69997029d7a5cfffcb8mreed    /* Close the socket */
76397903da2202008733f50e69997029d7a5cfffcb8mreed    close(sock_fd);
76497903da2202008733f50e69997029d7a5cfffcb8mreed}
76597903da2202008733f50e69997029d7a5cfffcb8mreed
76697903da2202008733f50e69997029d7a5cfffcb8mreed/*
76797903da2202008733f50e69997029d7a5cfffcb8mreed *
76897903da2202008733f50e69997029d7a5cfffcb8mreed *  Function: main()
76997903da2202008733f50e69997029d7a5cfffcb8mreed *
77097903da2202008733f50e69997029d7a5cfffcb8mreed */
77197903da2202008733f50e69997029d7a5cfffcb8mreedint
77297903da2202008733f50e69997029d7a5cfffcb8mreedmain(int argc, char *argv[])
77397903da2202008733f50e69997029d7a5cfffcb8mreed{
77497903da2202008733f50e69997029d7a5cfffcb8mreed    struct icmp6_info icmp6_data;
77597903da2202008733f50e69997029d7a5cfffcb8mreed    int background = 0;
77697903da2202008733f50e69997029d7a5cfffcb8mreed
77797903da2202008733f50e69997029d7a5cfffcb8mreed    debug = 0;
77897903da2202008733f50e69997029d7a5cfffcb8mreed    program_name = strdup(argv[0]);
77997903da2202008733f50e69997029d7a5cfffcb8mreed
78097903da2202008733f50e69997029d7a5cfffcb8mreed    memset(&icmp6_data, '\0', sizeof(struct icmp6_info));
78197903da2202008733f50e69997029d7a5cfffcb8mreed    parse_options(argc, argv, &icmp6_data, &background);
78297903da2202008733f50e69997029d7a5cfffcb8mreed
78397903da2202008733f50e69997029d7a5cfffcb8mreed    if (background)     /* Work in the background */
78497903da2202008733f50e69997029d7a5cfffcb8mreed	if (daemon(0, 0) < 0)
78597903da2202008733f50e69997029d7a5cfffcb8mreed	    fatal_error("daemon()");
78697903da2202008733f50e69997029d7a5cfffcb8mreed
78797903da2202008733f50e69997029d7a5cfffcb8mreed    send_packets(&icmp6_data);
78897903da2202008733f50e69997029d7a5cfffcb8mreed
78997903da2202008733f50e69997029d7a5cfffcb8mreed    exit(EXIT_SUCCESS);
790ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman}
791