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 */ 174548c6cf9bcdd96d8303caa4130ab638b61f8a30Wanlong Gao/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 { 60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ip6_datagram pkt; 61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct sockaddr_ll saddr_ll; 62354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct sockaddr_ll daddr_ll; 63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct in6_addr saddr; 64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct in6_addr daddr; 65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned short int pkt_size; 66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned short int data_size; 67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double timeout; 68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct timespec interval; 69354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 70354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 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 */ 94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid usage(char *program_name, int exit_value) 9597903da2202008733f50e69997029d7a5cfffcb8mreed{ 96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FILE *stream = stdout; /* stream where the usage is output */ 97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (exit_value == EXIT_FAILURE) 99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao stream = stderr; 100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stream, "%s [OPTION]\n" 102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-I if_name\tInterface name of the source host\n" 103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-S ip_addr\tIPv6 address of the source host\n" 104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-M mac_addr\tMAC address of the destination host\n" 105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-D ip_addr\tIPv6 address of the destination host\n" 106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-t value\ttimeout [sec]\n" 107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-w value\tinterval [nanosec]\n" 108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-o\t\tsend only one ICMPv6 message\n" 109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-b\t\twork in the background\n" 110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-d\t\tdisplay debug informations\n" 111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t-h\t\tdisplay this usage\n" 112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\n" 113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t[options for echo request]\n" 114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -s packetsize\tsize of data (exclude header)\n" 115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\n" 116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t[options for fake]\n" 117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -i\t\tbreak IPv6 destination address\n" 118354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -L\t\tbreak payload length\n" 119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -n\t\tbreak next header\n" 120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -v\t\tbreak IP version\n" 121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\n" 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t[options for MLDv2 query]\n" 123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -m\t\tsend MLDv2 query\n" 124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -a addrs\tcomma separated array of Source Addresses\n" 125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "\t -r value\tMax Resp Code\n", program_name); 126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(exit_value); 12797903da2202008733f50e69997029d7a5cfffcb8mreed} 12897903da2202008733f50e69997029d7a5cfffcb8mreed 12997903da2202008733f50e69997029d7a5cfffcb8mreed/* 13097903da2202008733f50e69997029d7a5cfffcb8mreed * Function: set_signal_flag() 13197903da2202008733f50e69997029d7a5cfffcb8mreed * 13297903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 13397903da2202008733f50e69997029d7a5cfffcb8mreed * This function sets global variables according to signal 13497903da2202008733f50e69997029d7a5cfffcb8mreed * 13597903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 13697903da2202008733f50e69997029d7a5cfffcb8mreed * type: type of signal 13797903da2202008733f50e69997029d7a5cfffcb8mreed * 13897903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 13997903da2202008733f50e69997029d7a5cfffcb8mreed * None 14097903da2202008733f50e69997029d7a5cfffcb8mreed */ 141354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid set_signal_flag(int type) 14297903da2202008733f50e69997029d7a5cfffcb8mreed{ 143354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 144354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Catch signal. type is %d\n", type); 14597903da2202008733f50e69997029d7a5cfffcb8mreed 146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao switch (type) { 14797903da2202008733f50e69997029d7a5cfffcb8mreed case SIGHUP: 148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao catch_sighup = 1; 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao handler.sa_handler = SIG_IGN; 150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sigaction(type, &handler, NULL) < 0) 151354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("sigaction()"); 152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 15397903da2202008733f50e69997029d7a5cfffcb8mreed 15497903da2202008733f50e69997029d7a5cfffcb8mreed default: 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Unexpected signal (%d) is caught\n", type); 156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 15897903da2202008733f50e69997029d7a5cfffcb8mreed} 15997903da2202008733f50e69997029d7a5cfffcb8mreed 16097903da2202008733f50e69997029d7a5cfffcb8mreed/* 16197903da2202008733f50e69997029d7a5cfffcb8mreed * Function: specify_hw_addr() 16297903da2202008733f50e69997029d7a5cfffcb8mreed * 16397903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 16497903da2202008733f50e69997029d7a5cfffcb8mreed * This function specifies the hardware address from the interface name 16597903da2202008733f50e69997029d7a5cfffcb8mreed * 16697903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 16797903da2202008733f50e69997029d7a5cfffcb8mreed * lladdr_p: pointer to the sockaddr_ll structure 16897903da2202008733f50e69997029d7a5cfffcb8mreed * ifname: interface name where icmpv6 messages go out 16997903da2202008733f50e69997029d7a5cfffcb8mreed * 17097903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 17197903da2202008733f50e69997029d7a5cfffcb8mreed * None 17297903da2202008733f50e69997029d7a5cfffcb8mreed * 17397903da2202008733f50e69997029d7a5cfffcb8mreed */ 174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid specify_hw_addr(struct sockaddr_ll *lladdr_p, const char *ifname) 17597903da2202008733f50e69997029d7a5cfffcb8mreed{ 176354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int sock_fd; /* Socket for ioctl() */ 177354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ifreq ifinfo; /* Interface information */ 17897903da2202008733f50e69997029d7a5cfffcb8mreed 179354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0) 180354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("socket()"); 18197903da2202008733f50e69997029d7a5cfffcb8mreed 182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_family = AF_PACKET; /* Always AF_PACKET */ 183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_hatype = ARPHRD_ETHER; /* Header type */ 185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_pkttype = PACKET_HOST; /* Packet type */ 186354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_halen = ETH_ALEN; /* Length of address */ 18797903da2202008733f50e69997029d7a5cfffcb8mreed 188354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Get the MAC address of the interface at source host */ 189354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao get_ifinfo(&ifinfo, sock_fd, ifname, SIOCGIFHWADDR); 190354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(lladdr_p->sll_addr, ifinfo.ifr_hwaddr.sa_data, ETH_ALEN); 19197903da2202008733f50e69997029d7a5cfffcb8mreed 192354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Get the interface index */ 193354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_ifindex = if_nametoindex(ifname); 194354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao close(sock_fd); 19597903da2202008733f50e69997029d7a5cfffcb8mreed} 19697903da2202008733f50e69997029d7a5cfffcb8mreed 19797903da2202008733f50e69997029d7a5cfffcb8mreed/* 19897903da2202008733f50e69997029d7a5cfffcb8mreed * Function: calc_hd_mcastaddr 19997903da2202008733f50e69997029d7a5cfffcb8mreed * 20097903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 20197903da2202008733f50e69997029d7a5cfffcb8mreed * This function calculate multicast hardware address from IPv6 20297903da2202008733f50e69997029d7a5cfffcb8mreed * multicast address 20397903da2202008733f50e69997029d7a5cfffcb8mreed * 20497903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 20597903da2202008733f50e69997029d7a5cfffcb8mreed * lladdr_p: pointer to the sockaddr_ll structure 20697903da2202008733f50e69997029d7a5cfffcb8mreed * addr_p: pointer to the in6_addr structure 20797903da2202008733f50e69997029d7a5cfffcb8mreed * 20897903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 20997903da2202008733f50e69997029d7a5cfffcb8mreed * None 21097903da2202008733f50e69997029d7a5cfffcb8mreed */ 211354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid calc_hd_mcastaddr(struct sockaddr_ll *lladdr_p, struct in6_addr *addr_p) 21297903da2202008733f50e69997029d7a5cfffcb8mreed{ 213354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_family = AF_PACKET; /* Always AF_PACKET */ 214354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 215354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_ifindex = 0; /* Unspecified here */ 216354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_hatype = ARPHRD_ETHER; /* Header type */ 217354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_pkttype = PACKET_MULTICAST; /* Packet type */ 218354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_halen = ETH_ALEN; /* Length of address */ 219354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 220354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_addr[0] = 0x33; 221354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lladdr_p->sll_addr[1] = 0x33; 222354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(&lladdr_p->sll_addr[2], &addr_p->s6_addr[12], ETH_ALEN - 2); 22397903da2202008733f50e69997029d7a5cfffcb8mreed} 22497903da2202008733f50e69997029d7a5cfffcb8mreed 22597903da2202008733f50e69997029d7a5cfffcb8mreed/* 22697903da2202008733f50e69997029d7a5cfffcb8mreed * Function: create_mld_query() 22797903da2202008733f50e69997029d7a5cfffcb8mreed * 22897903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 22997903da2202008733f50e69997029d7a5cfffcb8mreed * This function create a mldv2 query information. 23097903da2202008733f50e69997029d7a5cfffcb8mreed * 23197903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 23297903da2202008733f50e69997029d7a5cfffcb8mreed * info_p: pointer to data of icmp structure 23397903da2202008733f50e69997029d7a5cfffcb8mreed * mrc: Max Resp Code 23497903da2202008733f50e69997029d7a5cfffcb8mreed * saddrs: comma separated array of the source addresses 23597903da2202008733f50e69997029d7a5cfffcb8mreed * 23697903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 23797903da2202008733f50e69997029d7a5cfffcb8mreed * 0: Success 23897903da2202008733f50e69997029d7a5cfffcb8mreed * 1: Fail 23997903da2202008733f50e69997029d7a5cfffcb8mreed */ 240354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint create_mld_query(struct icmp6_info *info_p, uint16_t mrc, char *saddrs) 24197903da2202008733f50e69997029d7a5cfffcb8mreed{ 242354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ip6_datagram pkt; /* ICMPv6 packet */ 243354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct hbh_router_alert *alart_p; /* pointer to router alart */ 244354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct my_mldv2_query *query_p; /* pointer to my_mldv2_query */ 245354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct pseudo_ip6_datagram pseudo; /* ICMPv6 pseudo packet for checksum */ 246354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint16_t numsrc; /* number of source address */ 247354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned short int ip6_psize; /* size of IPv6 payload */ 248354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned short int query_size; /* size of my_mldv2_query */ 249354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct in6_addr ip6; 250354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint32_t idx; 251354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *sp, *ep; 252354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 253354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&pkt, '\0', sizeof(struct ip6_datagram)); 254354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p = (struct hbh_router_alert *)&(pkt.payload); 255354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p = 256354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (struct my_mldv2_query *)((unsigned char *)alart_p + 257354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(struct hbh_router_alert)); 258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 259354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* calculate the number of source address */ 260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (saddrs == NULL) { 261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao numsrc = 0; 262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao numsrc = 1; 264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (sp = saddrs; *sp != '\0'; sp++) 265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (*sp == ',') 266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao numsrc++; 267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 26897903da2202008733f50e69997029d7a5cfffcb8mreed if (debug) 269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "number of source address is %u\n", numsrc); 270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_size = MY_MLDV2_QUERY_SIZE(numsrc); 272354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ip6_psize = sizeof(struct hbh_router_alert) + query_size; 273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* IPv6 Header */ 275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_vfc = 6 << 4; 276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_flow |= 0; 277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_plen = htons(ip6_psize); 278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_nxt = IPPROTO_HOPOPTS; 279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_hlim = 1; 280354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_src = info_p->saddr; 281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_dst = info_p->daddr; 282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Router Alert Option */ 284354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->nxthdr = IPPROTO_ICMPV6; 285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->hbh_len = 0; 286354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->alart_type = 0x05; /* router alert */ 287354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->alart_len = 0x02; /* data len */ 288354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->alart_data = htons(0x0000); /* MLD */ 289354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->padn_type = 0x01; /* PadN option */ 290354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao alart_p->padn_len = 0x00; /* 2 Octets */ 291354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 292354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* MLDv2 query */ 293354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->type = MLD_LISTENER_QUERY; 294354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->code = 0; 295354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->cksum = 0; /* Calculate later */ 296354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->maxdelay = htons(mrc); 297354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->resv = 0; 298354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->suppress = 0; 299354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->qrv = 0; 300354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->qqic = 0; 301354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->nsrcs = htons(numsrc); 302354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 303354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* define the multicast address */ 304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (memcmp(&info_p->daddr, &in6addr_allnodes, sizeof(struct in6_addr)) 305354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao == 0) 306354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->addr = in6addr_any; 307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao else 308354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->addr = info_p->daddr; 309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* substitute source addresses */ 311354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sp = saddrs; 312354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (idx = 0; idx < numsrc; idx++) { 313354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ep = strchr(sp, ','); 314354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ep != NULL) 315354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao *ep = '\0'; 316354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 317354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "source address[%u]: %s\n", idx, sp); 31897903da2202008733f50e69997029d7a5cfffcb8mreed 319354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (inet_pton(AF_INET6, sp, &ip6) <= 0) { 320354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 321354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "source address list is something wrong\n"); 322354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 1; 323354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 324354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->srcs[idx] = ip6; 325354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sp = ep + 1; 32697903da2202008733f50e69997029d7a5cfffcb8mreed } 327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 328354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* ICMPv6 Pseudo packet */ 329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_src = pkt.hdr.ip6_src; 330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_dst = pkt.hdr.ip6_dst; 331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_plen = htons(query_size); 332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_zero1 = 0; 333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_zero2 = 0; 334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_nxt = IPPROTO_ICMPV6; 335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(pseudo.payload, query_p, query_size); 336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Calcualte checksums */ 338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_p->cksum = calc_checksum((u_int16_t *) (&pseudo), 339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(struct pseudo_ip6_hdr) + 340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao query_size); 341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Store the clean packet data */ 343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->pkt = pkt; 344354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize; 345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 346354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 0; 34797903da2202008733f50e69997029d7a5cfffcb8mreed} 34897903da2202008733f50e69997029d7a5cfffcb8mreed 34997903da2202008733f50e69997029d7a5cfffcb8mreed/* 35097903da2202008733f50e69997029d7a5cfffcb8mreed * Function: create_echo_request() 35197903da2202008733f50e69997029d7a5cfffcb8mreed * 35297903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 35397903da2202008733f50e69997029d7a5cfffcb8mreed * This function creates icmpv6 echo request 35497903da2202008733f50e69997029d7a5cfffcb8mreed * 35597903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 35697903da2202008733f50e69997029d7a5cfffcb8mreed * info_p: pointer to data of icmp structure 35797903da2202008733f50e69997029d7a5cfffcb8mreed * 35897903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 35997903da2202008733f50e69997029d7a5cfffcb8mreed * None 36097903da2202008733f50e69997029d7a5cfffcb8mreed */ 361354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid create_echo_request(struct icmp6_info *info_p) 36297903da2202008733f50e69997029d7a5cfffcb8mreed{ 363354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ip6_datagram pkt; /* ICMPv6 packet */ 364354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct icmp6_segment *echoreq_p; /* Echo request header and payload */ 365354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct pseudo_ip6_datagram pseudo; /* ICMPv6 pseudo packet for checksum */ 366354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned short int ip6_psize; /* payload size */ 367354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 368354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ip6_psize = sizeof(struct icmp6_hdr) /* ICMP header */ 369354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao +info_p->data_size; /* ICMP payload */ 370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&pkt, '\0', sizeof(struct ip6_datagram)); 371354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p = (struct icmp6_segment *)&(pkt.payload); 372354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* IPv6 Header */ 374354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_vfc = 6 << 4; 375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_flow |= 0; 376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_plen = htons(ip6_psize); 377354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_nxt = IPPROTO_ICMPV6; 378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_hlim = IPV6_DEFAULT_HOPLIMIT; 379354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_src = info_p->saddr; 380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt.hdr.ip6_dst = info_p->daddr; 381354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 382354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Echo Request Header */ 383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_type = ICMP6_ECHO_REQUEST; 384354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_code = 0; 385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_cksum = 0; /* Calculate later */ 386354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_id = htons(ICMP_ECHO_ID); 387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_seq = htons(1); 388354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 389354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Echo Request Payload */ 390354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fill_payload(echoreq_p->data, info_p->data_size); 391354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 392354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* ICMPv6 Pseudo packet */ 393354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_src = pkt.hdr.ip6_src; 394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_dst = pkt.hdr.ip6_dst; 395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_plen = htons(ip6_psize); 396354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_zero1 = 0; 397354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_zero2 = 0; 398354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pseudo.hdr.p_ip6_nxt = IPPROTO_ICMPV6; 399354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(pseudo.payload, echoreq_p, ip6_psize); 400354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 401354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Calcualte checksums */ 402354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao echoreq_p->hdr.icmp6_cksum = calc_checksum((u_int16_t *) (&pseudo), 403354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(struct pseudo_ip6_hdr) 404354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao + ip6_psize); 405354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Store the clean packet data */ 407354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->pkt = pkt; 408354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize; 40997903da2202008733f50e69997029d7a5cfffcb8mreed} 41097903da2202008733f50e69997029d7a5cfffcb8mreed 41197903da2202008733f50e69997029d7a5cfffcb8mreed/* 41297903da2202008733f50e69997029d7a5cfffcb8mreed * Function: parse_options() 41397903da2202008733f50e69997029d7a5cfffcb8mreed * 41497903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 41597903da2202008733f50e69997029d7a5cfffcb8mreed * This function parse the options 41697903da2202008733f50e69997029d7a5cfffcb8mreed * 41797903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 41897903da2202008733f50e69997029d7a5cfffcb8mreed * argc: the number of argument 41997903da2202008733f50e69997029d7a5cfffcb8mreed * argv: arguments 42097903da2202008733f50e69997029d7a5cfffcb8mreed * info_p: pointer to data of icmp data to modify 42197903da2202008733f50e69997029d7a5cfffcb8mreed * bg_p: pointer to the flag of working in backgrond 42297903da2202008733f50e69997029d7a5cfffcb8mreed * 42397903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 42497903da2202008733f50e69997029d7a5cfffcb8mreed * None 42597903da2202008733f50e69997029d7a5cfffcb8mreed */ 426354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid parse_options(int argc, char *argv[], struct icmp6_info *info_p, int *bg_p) 42797903da2202008733f50e69997029d7a5cfffcb8mreed{ 428354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int optc; /* option */ 429354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned long opt_ul; /* option value in unsigned long */ 430354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double opt_d; /* option value in double */ 431354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct in6_addr opt_addr; /* option value in struct in_addr */ 432354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct sockaddr_ll opt_addr_ll; /* option value in struct sockaddr_ll */ 433354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *ifname; /* interface name where datagrams go out */ 434354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int is_mld_query; /* set to non-zero if sending MLDv2 query */ 435354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *mld_saddrs; /* comma separated array of source addresses */ 436354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint16_t max_resp; /* Max Resp Code */ 437354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int is_specified_daddr_ll = 0; 438354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int is_specified_saddr = 0; 439354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int is_specified_daddr = 0; 440354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 441354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ifname = NULL; 442354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao is_mld_query = 0; 443354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao mld_saddrs = NULL; 444354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao max_resp = MY_MLD_MAX_HOST_REPORT_DELAY; 445354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 446354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while ((optc = 447354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao getopt(argc, argv, "I:S:M:D:t:w:obdhs:iLnvma:r:")) != EOF) { 448354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao switch (optc) { 449354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'I': 450354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (if_nametoindex(optarg) == 0) { 451354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 452354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "specified interface is incorrect\n"); 453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 455354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ifname = strdup(optarg); 456354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ifname == NULL) 457354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("strdup() failed."); 458354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 459354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 460354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'S': 461354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { 462354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Source address is wrong\n"); 463354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 464354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 465354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->saddr = opt_addr; 466354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao is_specified_saddr = 1; 467354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 468354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 469354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'M': 470354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (eth_pton(AF_INET6, optarg, &opt_addr_ll)) { 471354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 472354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Destination MAC address is wrong\n"); 473354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 474354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 475354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->daddr_ll = opt_addr_ll; 476354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao is_specified_daddr_ll = 1; 477354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 478354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 479354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'D': 480354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { 481354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 482354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Destination address is wrong\n"); 483354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 484354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 485354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->daddr = opt_addr; 486354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao is_specified_daddr = 1; 487354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 488354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 489354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 't': 490354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao opt_d = strtod(optarg, NULL); 491354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (opt_d < 0.0) { 492354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 493354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Timeout should be positive value\n"); 494354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 495354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 496354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->timeout = opt_d; 497354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 498354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 499354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'w': 500354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (strtotimespec(optarg, &info_p->interval)) { 501354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 502354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Interval is something wrong\n"); 503354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 504354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 505354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 506354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 507354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'o': 508354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->timeout = -1.0; 509354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 510354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 511354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'b': 512354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao *bg_p = 1; 513354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 514354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 515354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'd': 516354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao debug = 1; 517354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 518354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 519354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'h': 520354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_SUCCESS); 521354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 522354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 523354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Options for echo request */ 524354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 's': 525354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao opt_ul = strtoul(optarg, NULL, 0); 526354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (opt_ul > ICMPV6_DATA_MAXSIZE) { 527354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 528354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Data size sholud be less than %d\n", 529354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ICMPV6_DATA_MAXSIZE + 1); 530354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 531354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 532354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->data_size = opt_ul; 533354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 534354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 535354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Options for fake */ 536354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'i': 537354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->fake_flag |= FAKE_DADDR; 538354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 539354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 540354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'L': 541354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->fake_flag |= FAKE_PLEN; 542354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 543354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 544354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'n': 545354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->fake_flag |= FAKE_NXT; 546354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 547354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 548354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'v': 549354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->fake_flag |= FAKE_VERSION; 550354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 551354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 552354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Options for MLDv2 query */ 553354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'm': 554354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao is_mld_query = 1; 555354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 556354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 557354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'a': 558354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao mld_saddrs = strdup(optarg); 559354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (mld_saddrs == NULL) 560354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("strdup()"); 561354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 562354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 563354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'r': 564354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao opt_ul = strtoul(optarg, NULL, 0); 565354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (opt_ul > 0xFFFF) { 566354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 567354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Max Resp Code should be less than 65536\n"); 568354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 569354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 570354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao max_resp = opt_ul; 571354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 57297903da2202008733f50e69997029d7a5cfffcb8mreed 573354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao default: 574354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 57597903da2202008733f50e69997029d7a5cfffcb8mreed } 576354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 57797903da2202008733f50e69997029d7a5cfffcb8mreed 578354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ifname == NULL) { 579354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Outgoing interface is not specified\n"); 580354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 581354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 582354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao specify_hw_addr(&info_p->saddr_ll, ifname); 58397903da2202008733f50e69997029d7a5cfffcb8mreed 584354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (!is_specified_saddr) { 585354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Source IP address is not specified\n"); 586354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 587354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 58897903da2202008733f50e69997029d7a5cfffcb8mreed 589354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (is_mld_query) { /* MLDv2 query */ 590354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (info_p->fake_flag) { 591354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 592354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "It is not permitted to break MLDv2 query\n"); 593354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 59497903da2202008733f50e69997029d7a5cfffcb8mreed } 59597903da2202008733f50e69997029d7a5cfffcb8mreed 596354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (!is_specified_daddr) 597354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->daddr = in6addr_allnodes; 59897903da2202008733f50e69997029d7a5cfffcb8mreed 599354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao calc_hd_mcastaddr(&info_p->daddr_ll, &info_p->daddr); 600354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (create_mld_query(info_p, max_resp, mld_saddrs)) 601354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 602354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { /* echo request */ 603354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (info_p->fake_flag) 604354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao srand(getpid()); 60597903da2202008733f50e69997029d7a5cfffcb8mreed 606354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (!is_specified_daddr_ll) { 607354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 608354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Destination MAC address is not specified\n"); 609354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 61097903da2202008733f50e69997029d7a5cfffcb8mreed } 61197903da2202008733f50e69997029d7a5cfffcb8mreed 612354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (!is_specified_daddr) { 613354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 614354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Destination IP address is not specified\n"); 615354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(program_name, EXIT_FAILURE); 61697903da2202008733f50e69997029d7a5cfffcb8mreed } 61797903da2202008733f50e69997029d7a5cfffcb8mreed 618354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao create_echo_request(info_p); 61997903da2202008733f50e69997029d7a5cfffcb8mreed } 620354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao info_p->daddr_ll.sll_ifindex = if_nametoindex(ifname); 62197903da2202008733f50e69997029d7a5cfffcb8mreed} 62297903da2202008733f50e69997029d7a5cfffcb8mreed 62397903da2202008733f50e69997029d7a5cfffcb8mreed/* 62497903da2202008733f50e69997029d7a5cfffcb8mreed * Function: thrust_fakes() 62597903da2202008733f50e69997029d7a5cfffcb8mreed * 62697903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 62797903da2202008733f50e69997029d7a5cfffcb8mreed * This function thrust fake information to the icmp packet 62897903da2202008733f50e69997029d7a5cfffcb8mreed * 62997903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 63097903da2202008733f50e69997029d7a5cfffcb8mreed * pkt : Payload of the Ethernet frame (Namely, IPv6 packet) 63197903da2202008733f50e69997029d7a5cfffcb8mreed * fake_flag: Flag which represents what information would be faked 63297903da2202008733f50e69997029d7a5cfffcb8mreed * 63397903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 63497903da2202008733f50e69997029d7a5cfffcb8mreed * None 63597903da2202008733f50e69997029d7a5cfffcb8mreed */ 636354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid thrust_fakes(struct ip6_datagram *pkt, u_int16_t fake_flag) 63797903da2202008733f50e69997029d7a5cfffcb8mreed{ 638354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int rand_val; 639354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t bitsize; 640354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao u_int32_t seed; 64197903da2202008733f50e69997029d7a5cfffcb8mreed 642354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 643354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "fake_flag = %2x\n", fake_flag); 644354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 645354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (fake_flag & FAKE_VERSION) { /* version */ 646354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao bitsize = 4; 647354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao seed = bit_change_seed(bitsize, 1); 648354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt->hdr.ip6_vfc ^= (seed << 4); 649354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 650354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 651354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (fake_flag & FAKE_PLEN) { /* total length */ 652354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao bitsize = sizeof(pkt->hdr.ip6_plen) * 8; 653354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao seed = bit_change_seed(bitsize, bitsize / 8); 654354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt->hdr.ip6_plen ^= seed; 655354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 656354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 657354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (fake_flag & FAKE_NXT) { /* next header */ 658354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rand_val = rand() / ((RAND_MAX + 1U) / 5); 659354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao switch (rand_val) { 660354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 1: 661354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 2: 662354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 663354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Bit reverse\n"); 664354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao bitsize = sizeof(pkt->hdr.ip6_nxt) * 8; 665354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao seed = bit_change_seed(bitsize, 0); 666354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt->hdr.ip6_nxt ^= seed; 667354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 668354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 669354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 3: 670354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 4: 671354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 672354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Unknown Protocol\n"); 673354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rand_val) { 674354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int number; 675354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int counter; 676354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (counter = 0; counter <= 0xff; counter++) { 677354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao number = 678354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rand() / ((RAND_MAX + 1U) / 0x100); 679354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (getprotobynumber(number) == NULL) { 680354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt->hdr.ip6_nxt = number; 681354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 682354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 683354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 68497903da2202008733f50e69997029d7a5cfffcb8mreed } 685354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 686354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 687354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao default: 688354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 689354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Do nothing\n"); 690354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 69197903da2202008733f50e69997029d7a5cfffcb8mreed } 692354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 69397903da2202008733f50e69997029d7a5cfffcb8mreed 694354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (fake_flag & FAKE_DADDR) { /* destination address */ 695354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rand_val = rand() / ((RAND_MAX + 1U) / 4); 696354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao bitsize = sizeof(pkt->hdr.ip6_dst.s6_addr32[rand_val]) * 8; 697354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao seed = bit_change_seed(bitsize, bitsize / 8); 698354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt->hdr.ip6_dst.s6_addr32[rand_val] ^= seed; 69997903da2202008733f50e69997029d7a5cfffcb8mreed } 70097903da2202008733f50e69997029d7a5cfffcb8mreed} 70197903da2202008733f50e69997029d7a5cfffcb8mreed 70297903da2202008733f50e69997029d7a5cfffcb8mreed/* 70397903da2202008733f50e69997029d7a5cfffcb8mreed * Function: send_packet() 70497903da2202008733f50e69997029d7a5cfffcb8mreed * 70597903da2202008733f50e69997029d7a5cfffcb8mreed * Description: 70697903da2202008733f50e69997029d7a5cfffcb8mreed * This function sends icmpv6 packet 70797903da2202008733f50e69997029d7a5cfffcb8mreed * 70897903da2202008733f50e69997029d7a5cfffcb8mreed * Argument: 70997903da2202008733f50e69997029d7a5cfffcb8mreed * info_p: pointer to data of icmp structure 71097903da2202008733f50e69997029d7a5cfffcb8mreed * 71197903da2202008733f50e69997029d7a5cfffcb8mreed * Return value: 71297903da2202008733f50e69997029d7a5cfffcb8mreed * None 71397903da2202008733f50e69997029d7a5cfffcb8mreed */ 714354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid send_packets(struct icmp6_info *info_p) 71597903da2202008733f50e69997029d7a5cfffcb8mreed{ 716354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int sock_fd; 717354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int retval; 718354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ip6_datagram pkt; 719354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao double start_time; 720354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 721354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Open a socket */ 722354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); 723354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sock_fd < 0) 724354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("socket()"); 725354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 726354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Bind the socket to the physical address */ 727354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao retval = bind(sock_fd, (struct sockaddr *)&(info_p->saddr_ll), 728354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(struct sockaddr_ll)); 72997903da2202008733f50e69997029d7a5cfffcb8mreed if (retval < 0) 730354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("bind()"); 731354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 732354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Set singal hander for SIGHUP */ 733354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao handler.sa_handler = set_signal_flag; 734354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao handler.sa_flags = 0; 735354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sigfillset(&handler.sa_mask) < 0) 736354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("sigfillset()"); 737354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sigaction(SIGHUP, &handler, NULL) < 0) 738354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("sigfillset()"); 739354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 740354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* 741354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao * loop for sending packets 742354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao */ 743354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt = info_p->pkt; 744354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao start_time = time(NULL); 745354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 746354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (;;) { 747354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (info_p->fake_flag) { 748354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pkt = info_p->pkt; 749354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao thrust_fakes(&pkt, info_p->fake_flag); 750354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 75197903da2202008733f50e69997029d7a5cfffcb8mreed 752354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao retval = sendto(sock_fd, &pkt, info_p->pkt_size, 0, 753354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (struct sockaddr *)&(info_p->daddr_ll), 754354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(struct sockaddr_ll)); 755354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (retval < 0) 756354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("sendto()"); 75797903da2202008733f50e69997029d7a5cfffcb8mreed 758354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Check timeout: 759354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao If timeout value is negative only send one datagram */ 760354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (info_p->timeout) 761354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (info_p->timeout < difftime(time(NULL), start_time)) 762354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 76397903da2202008733f50e69997029d7a5cfffcb8mreed 764354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Wait in specified interval */ 765354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao nanosleep(&info_p->interval, NULL); 766354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 767354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (catch_sighup) /* catch SIGHUP */ 768354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 769354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 77097903da2202008733f50e69997029d7a5cfffcb8mreed 771354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Close the socket */ 772354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao close(sock_fd); 77397903da2202008733f50e69997029d7a5cfffcb8mreed} 77497903da2202008733f50e69997029d7a5cfffcb8mreed 77597903da2202008733f50e69997029d7a5cfffcb8mreed/* 77697903da2202008733f50e69997029d7a5cfffcb8mreed * 77797903da2202008733f50e69997029d7a5cfffcb8mreed * Function: main() 77897903da2202008733f50e69997029d7a5cfffcb8mreed * 77997903da2202008733f50e69997029d7a5cfffcb8mreed */ 780354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint main(int argc, char *argv[]) 78197903da2202008733f50e69997029d7a5cfffcb8mreed{ 782354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct icmp6_info icmp6_data; 783354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int background = 0; 78497903da2202008733f50e69997029d7a5cfffcb8mreed 785354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao debug = 0; 786354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao program_name = strdup(argv[0]); 78797903da2202008733f50e69997029d7a5cfffcb8mreed 788354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&icmp6_data, '\0', sizeof(struct icmp6_info)); 789354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao parse_options(argc, argv, &icmp6_data, &background); 79097903da2202008733f50e69997029d7a5cfffcb8mreed 791354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (background) /* Work in the background */ 792354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (daemon(0, 0) < 0) 793354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("daemon()"); 79497903da2202008733f50e69997029d7a5cfffcb8mreed 795354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao send_packets(&icmp6_data); 79697903da2202008733f50e69997029d7a5cfffcb8mreed 797354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_SUCCESS); 798ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 799