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