1f08c3bdfSopenharmony_ci/******************************************************************************/ 2f08c3bdfSopenharmony_ci/* */ 3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines Corp., 2006 */ 4f08c3bdfSopenharmony_ci/* */ 5f08c3bdfSopenharmony_ci/* This program is free software; you can redistribute it and/or modify */ 6f08c3bdfSopenharmony_ci/* it under the terms of the GNU General Public License as published by */ 7f08c3bdfSopenharmony_ci/* the Free Software Foundation; either version 2 of the License, or */ 8f08c3bdfSopenharmony_ci/* (at your option) any later version. */ 9f08c3bdfSopenharmony_ci/* */ 10f08c3bdfSopenharmony_ci/* This program is distributed in the hope that it will be useful, */ 11f08c3bdfSopenharmony_ci/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12f08c3bdfSopenharmony_ci/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13f08c3bdfSopenharmony_ci/* the GNU General Public License for more details. */ 14f08c3bdfSopenharmony_ci/* */ 15f08c3bdfSopenharmony_ci/* You should have received a copy of the GNU General Public License */ 16f08c3bdfSopenharmony_ci/* along with this program; if not, write to the Free Software */ 17f08c3bdfSopenharmony_ci/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 18f08c3bdfSopenharmony_ci/* */ 19f08c3bdfSopenharmony_ci/******************************************************************************/ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ci/* 22f08c3bdfSopenharmony_ci * File: 23f08c3bdfSopenharmony_ci * ns-icmpv6_sender.c 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Description: 26f08c3bdfSopenharmony_ci * This is ICMPv6 message (Echo request / MLDv2 query) sender. 27f08c3bdfSopenharmony_ci * This utility is also able to set illegal information in the IP header 28f08c3bdfSopenharmony_ci * 29f08c3bdfSopenharmony_ci * Author: 30f08c3bdfSopenharmony_ci * Mitsuru Chinen <mitch@jp.ibm.com> 31f08c3bdfSopenharmony_ci * 32f08c3bdfSopenharmony_ci * History: 33f08c3bdfSopenharmony_ci * Mar 15 2006 - Created (Mitsuru Chinen) 34f08c3bdfSopenharmony_ci *---------------------------------------------------------------------------*/ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci/* 37f08c3bdfSopenharmony_ci * Header Files 38f08c3bdfSopenharmony_ci */ 39f08c3bdfSopenharmony_ci#include <stdio.h> 40f08c3bdfSopenharmony_ci#include <stdlib.h> 41f08c3bdfSopenharmony_ci#include <string.h> 42f08c3bdfSopenharmony_ci#include <errno.h> 43f08c3bdfSopenharmony_ci#include <netdb.h> 44f08c3bdfSopenharmony_ci#include <signal.h> 45f08c3bdfSopenharmony_ci#include <time.h> 46f08c3bdfSopenharmony_ci#include <unistd.h> 47f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 48f08c3bdfSopenharmony_ci#include <sys/socket.h> 49f08c3bdfSopenharmony_ci#include <arpa/inet.h> 50f08c3bdfSopenharmony_ci#include <net/ethernet.h> 51f08c3bdfSopenharmony_ci#include <netinet/in.h> 52f08c3bdfSopenharmony_ci 53f08c3bdfSopenharmony_ci#include "ns-mcast.h" 54f08c3bdfSopenharmony_ci#include "ns-traffic.h" 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ci/* 57f08c3bdfSopenharmony_ci * Structure Definitions 58f08c3bdfSopenharmony_ci */ 59f08c3bdfSopenharmony_cistruct icmp6_info { 60f08c3bdfSopenharmony_ci struct ip6_datagram pkt; 61f08c3bdfSopenharmony_ci struct sockaddr_ll saddr_ll; 62f08c3bdfSopenharmony_ci struct sockaddr_ll daddr_ll; 63f08c3bdfSopenharmony_ci struct in6_addr saddr; 64f08c3bdfSopenharmony_ci struct in6_addr daddr; 65f08c3bdfSopenharmony_ci unsigned short int pkt_size; 66f08c3bdfSopenharmony_ci unsigned short int data_size; 67f08c3bdfSopenharmony_ci double timeout; 68f08c3bdfSopenharmony_ci struct timespec interval; 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci u_int16_t fake_flag; 71f08c3bdfSopenharmony_ci}; 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci/* 74f08c3bdfSopenharmony_ci * Gloval variables 75f08c3bdfSopenharmony_ci */ 76f08c3bdfSopenharmony_cichar *program_name; /* program name */ 77f08c3bdfSopenharmony_cistruct sigaction handler; /* Behavior for a signal */ 78f08c3bdfSopenharmony_ciint catch_sighup; /* When catch the SIGHUP, set to non-zero */ 79f08c3bdfSopenharmony_cistruct in6_addr in6addr_allnodes = IN6ADDR_ALLNODES_MULTICAST_INIT; 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci/* 82f08c3bdfSopenharmony_ci * Function: usage() 83f08c3bdfSopenharmony_ci * 84f08c3bdfSopenharmony_ci * Descripton: 85f08c3bdfSopenharmony_ci * Print the usage of this program. Then, terminate this program with 86f08c3bdfSopenharmony_ci * the specified exit value. 87f08c3bdfSopenharmony_ci * 88f08c3bdfSopenharmony_ci * Argument: 89f08c3bdfSopenharmony_ci * exit_value: exit value 90f08c3bdfSopenharmony_ci * 91f08c3bdfSopenharmony_ci * Return value: 92f08c3bdfSopenharmony_ci * This function does not return. 93f08c3bdfSopenharmony_ci */ 94f08c3bdfSopenharmony_civoid usage(char *program_name, int exit_value) 95f08c3bdfSopenharmony_ci{ 96f08c3bdfSopenharmony_ci FILE *stream = stdout; /* stream where the usage is output */ 97f08c3bdfSopenharmony_ci 98f08c3bdfSopenharmony_ci if (exit_value == EXIT_FAILURE) 99f08c3bdfSopenharmony_ci stream = stderr; 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci fprintf(stream, "%s [OPTION]\n" 102f08c3bdfSopenharmony_ci "\t-I if_name\tInterface name of the source host\n" 103f08c3bdfSopenharmony_ci "\t-S ip_addr\tIPv6 address of the source host\n" 104f08c3bdfSopenharmony_ci "\t-M mac_addr\tMAC address of the destination host\n" 105f08c3bdfSopenharmony_ci "\t-D ip_addr\tIPv6 address of the destination host\n" 106f08c3bdfSopenharmony_ci "\t-t value\ttimeout [sec]\n" 107f08c3bdfSopenharmony_ci "\t-w value\tinterval [nanosec]\n" 108f08c3bdfSopenharmony_ci "\t-o\t\tsend only one ICMPv6 message\n" 109f08c3bdfSopenharmony_ci "\t-b\t\twork in the background\n" 110f08c3bdfSopenharmony_ci "\t-d\t\tdisplay debug informations\n" 111f08c3bdfSopenharmony_ci "\t-h\t\tdisplay this usage\n" 112f08c3bdfSopenharmony_ci "\n" 113f08c3bdfSopenharmony_ci "\t[options for echo request]\n" 114f08c3bdfSopenharmony_ci "\t -s packetsize\tsize of data (exclude header)\n" 115f08c3bdfSopenharmony_ci "\n" 116f08c3bdfSopenharmony_ci "\t[options for fake]\n" 117f08c3bdfSopenharmony_ci "\t -i\t\tbreak IPv6 destination address\n" 118f08c3bdfSopenharmony_ci "\t -L\t\tbreak payload length\n" 119f08c3bdfSopenharmony_ci "\t -n\t\tbreak next header\n" 120f08c3bdfSopenharmony_ci "\t -v\t\tbreak IP version\n" 121f08c3bdfSopenharmony_ci "\n" 122f08c3bdfSopenharmony_ci "\t[options for MLDv2 query]\n" 123f08c3bdfSopenharmony_ci "\t -m\t\tsend MLDv2 query\n" 124f08c3bdfSopenharmony_ci "\t -a addrs\tcomma separated array of Source Addresses\n" 125f08c3bdfSopenharmony_ci "\t -r value\tMax Resp Code\n", program_name); 126f08c3bdfSopenharmony_ci exit(exit_value); 127f08c3bdfSopenharmony_ci} 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci/* 130f08c3bdfSopenharmony_ci * Function: set_signal_flag() 131f08c3bdfSopenharmony_ci * 132f08c3bdfSopenharmony_ci * Description: 133f08c3bdfSopenharmony_ci * This function sets global variables according to signal 134f08c3bdfSopenharmony_ci * 135f08c3bdfSopenharmony_ci * Argument: 136f08c3bdfSopenharmony_ci * type: type of signal 137f08c3bdfSopenharmony_ci * 138f08c3bdfSopenharmony_ci * Return value: 139f08c3bdfSopenharmony_ci * None 140f08c3bdfSopenharmony_ci */ 141f08c3bdfSopenharmony_civoid set_signal_flag(int type) 142f08c3bdfSopenharmony_ci{ 143f08c3bdfSopenharmony_ci if (debug) 144f08c3bdfSopenharmony_ci fprintf(stderr, "Catch signal. type is %d\n", type); 145f08c3bdfSopenharmony_ci 146f08c3bdfSopenharmony_ci switch (type) { 147f08c3bdfSopenharmony_ci case SIGHUP: 148f08c3bdfSopenharmony_ci catch_sighup = 1; 149f08c3bdfSopenharmony_ci handler.sa_handler = SIG_IGN; 150f08c3bdfSopenharmony_ci if (sigaction(type, &handler, NULL) < 0) 151f08c3bdfSopenharmony_ci fatal_error("sigaction()"); 152f08c3bdfSopenharmony_ci break; 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci default: 155f08c3bdfSopenharmony_ci fprintf(stderr, "Unexpected signal (%d) is caught\n", type); 156f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 157f08c3bdfSopenharmony_ci } 158f08c3bdfSopenharmony_ci} 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci/* 161f08c3bdfSopenharmony_ci * Function: specify_hw_addr() 162f08c3bdfSopenharmony_ci * 163f08c3bdfSopenharmony_ci * Description: 164f08c3bdfSopenharmony_ci * This function specifies the hardware address from the interface name 165f08c3bdfSopenharmony_ci * 166f08c3bdfSopenharmony_ci * Argument: 167f08c3bdfSopenharmony_ci * lladdr_p: pointer to the sockaddr_ll structure 168f08c3bdfSopenharmony_ci * ifname: interface name where icmpv6 messages go out 169f08c3bdfSopenharmony_ci * 170f08c3bdfSopenharmony_ci * Return value: 171f08c3bdfSopenharmony_ci * None 172f08c3bdfSopenharmony_ci * 173f08c3bdfSopenharmony_ci */ 174f08c3bdfSopenharmony_civoid specify_hw_addr(struct sockaddr_ll *lladdr_p, const char *ifname) 175f08c3bdfSopenharmony_ci{ 176f08c3bdfSopenharmony_ci int sock_fd; /* Socket for ioctl() */ 177f08c3bdfSopenharmony_ci struct ifreq ifinfo; /* Interface information */ 178f08c3bdfSopenharmony_ci 179f08c3bdfSopenharmony_ci if ((sock_fd = socket(AF_PACKET, SOCK_DGRAM, 0)) < 0) 180f08c3bdfSopenharmony_ci fatal_error("socket()"); 181f08c3bdfSopenharmony_ci 182f08c3bdfSopenharmony_ci lladdr_p->sll_family = AF_PACKET; /* Always AF_PACKET */ 183f08c3bdfSopenharmony_ci lladdr_p->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 184f08c3bdfSopenharmony_ci lladdr_p->sll_hatype = ARPHRD_ETHER; /* Header type */ 185f08c3bdfSopenharmony_ci lladdr_p->sll_pkttype = PACKET_HOST; /* Packet type */ 186f08c3bdfSopenharmony_ci lladdr_p->sll_halen = ETH_ALEN; /* Length of address */ 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci /* Get the MAC address of the interface at source host */ 189f08c3bdfSopenharmony_ci get_ifinfo(&ifinfo, sock_fd, ifname, SIOCGIFHWADDR); 190f08c3bdfSopenharmony_ci memcpy(lladdr_p->sll_addr, ifinfo.ifr_hwaddr.sa_data, ETH_ALEN); 191f08c3bdfSopenharmony_ci 192f08c3bdfSopenharmony_ci /* Get the interface index */ 193f08c3bdfSopenharmony_ci lladdr_p->sll_ifindex = if_nametoindex(ifname); 194f08c3bdfSopenharmony_ci close(sock_fd); 195f08c3bdfSopenharmony_ci} 196f08c3bdfSopenharmony_ci 197f08c3bdfSopenharmony_ci/* 198f08c3bdfSopenharmony_ci * Function: calc_hd_mcastaddr 199f08c3bdfSopenharmony_ci * 200f08c3bdfSopenharmony_ci * Description: 201f08c3bdfSopenharmony_ci * This function calculate multicast hardware address from IPv6 202f08c3bdfSopenharmony_ci * multicast address 203f08c3bdfSopenharmony_ci * 204f08c3bdfSopenharmony_ci * Argument: 205f08c3bdfSopenharmony_ci * lladdr_p: pointer to the sockaddr_ll structure 206f08c3bdfSopenharmony_ci * addr_p: pointer to the in6_addr structure 207f08c3bdfSopenharmony_ci * 208f08c3bdfSopenharmony_ci * Return value: 209f08c3bdfSopenharmony_ci * None 210f08c3bdfSopenharmony_ci */ 211f08c3bdfSopenharmony_civoid calc_hd_mcastaddr(struct sockaddr_ll *lladdr_p, struct in6_addr *addr_p) 212f08c3bdfSopenharmony_ci{ 213f08c3bdfSopenharmony_ci lladdr_p->sll_family = AF_PACKET; /* Always AF_PACKET */ 214f08c3bdfSopenharmony_ci lladdr_p->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 215f08c3bdfSopenharmony_ci lladdr_p->sll_ifindex = 0; /* Unspecified here */ 216f08c3bdfSopenharmony_ci lladdr_p->sll_hatype = ARPHRD_ETHER; /* Header type */ 217f08c3bdfSopenharmony_ci lladdr_p->sll_pkttype = PACKET_MULTICAST; /* Packet type */ 218f08c3bdfSopenharmony_ci lladdr_p->sll_halen = ETH_ALEN; /* Length of address */ 219f08c3bdfSopenharmony_ci 220f08c3bdfSopenharmony_ci lladdr_p->sll_addr[0] = 0x33; 221f08c3bdfSopenharmony_ci lladdr_p->sll_addr[1] = 0x33; 222f08c3bdfSopenharmony_ci memcpy(&lladdr_p->sll_addr[2], &addr_p->s6_addr[12], ETH_ALEN - 2); 223f08c3bdfSopenharmony_ci} 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci/* 226f08c3bdfSopenharmony_ci * Function: create_mld_query() 227f08c3bdfSopenharmony_ci * 228f08c3bdfSopenharmony_ci * Description: 229f08c3bdfSopenharmony_ci * This function create a mldv2 query information. 230f08c3bdfSopenharmony_ci * 231f08c3bdfSopenharmony_ci * Argument: 232f08c3bdfSopenharmony_ci * info_p: pointer to data of icmp structure 233f08c3bdfSopenharmony_ci * mrc: Max Resp Code 234f08c3bdfSopenharmony_ci * saddrs: comma separated array of the source addresses 235f08c3bdfSopenharmony_ci * 236f08c3bdfSopenharmony_ci * Return value: 237f08c3bdfSopenharmony_ci * 0: Success 238f08c3bdfSopenharmony_ci * 1: Fail 239f08c3bdfSopenharmony_ci */ 240f08c3bdfSopenharmony_ciint create_mld_query(struct icmp6_info *info_p, uint16_t mrc, char *saddrs) 241f08c3bdfSopenharmony_ci{ 242f08c3bdfSopenharmony_ci struct ip6_datagram pkt; /* ICMPv6 packet */ 243f08c3bdfSopenharmony_ci struct hbh_router_alert *alart_p; /* pointer to router alart */ 244f08c3bdfSopenharmony_ci struct my_mldv2_query *query_p; /* pointer to my_mldv2_query */ 245f08c3bdfSopenharmony_ci struct pseudo_ip6_datagram pseudo; /* ICMPv6 pseudo packet for checksum */ 246f08c3bdfSopenharmony_ci uint16_t numsrc; /* number of source address */ 247f08c3bdfSopenharmony_ci unsigned short int ip6_psize; /* size of IPv6 payload */ 248f08c3bdfSopenharmony_ci unsigned short int query_size; /* size of my_mldv2_query */ 249f08c3bdfSopenharmony_ci struct in6_addr ip6; 250f08c3bdfSopenharmony_ci uint32_t idx; 251f08c3bdfSopenharmony_ci char *sp, *ep; 252f08c3bdfSopenharmony_ci 253f08c3bdfSopenharmony_ci memset(&pkt, '\0', sizeof(struct ip6_datagram)); 254f08c3bdfSopenharmony_ci alart_p = (struct hbh_router_alert *)&(pkt.payload); 255f08c3bdfSopenharmony_ci query_p = 256f08c3bdfSopenharmony_ci (struct my_mldv2_query *)((unsigned char *)alart_p + 257f08c3bdfSopenharmony_ci sizeof(struct hbh_router_alert)); 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci /* calculate the number of source address */ 260f08c3bdfSopenharmony_ci if (saddrs == NULL) { 261f08c3bdfSopenharmony_ci numsrc = 0; 262f08c3bdfSopenharmony_ci } else { 263f08c3bdfSopenharmony_ci numsrc = 1; 264f08c3bdfSopenharmony_ci for (sp = saddrs; *sp != '\0'; sp++) 265f08c3bdfSopenharmony_ci if (*sp == ',') 266f08c3bdfSopenharmony_ci numsrc++; 267f08c3bdfSopenharmony_ci } 268f08c3bdfSopenharmony_ci if (debug) 269f08c3bdfSopenharmony_ci fprintf(stderr, "number of source address is %u\n", numsrc); 270f08c3bdfSopenharmony_ci 271f08c3bdfSopenharmony_ci query_size = MY_MLDV2_QUERY_SIZE(numsrc); 272f08c3bdfSopenharmony_ci ip6_psize = sizeof(struct hbh_router_alert) + query_size; 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci /* IPv6 Header */ 275f08c3bdfSopenharmony_ci pkt.hdr.ip6_vfc = 6 << 4; 276f08c3bdfSopenharmony_ci pkt.hdr.ip6_flow |= 0; 277f08c3bdfSopenharmony_ci pkt.hdr.ip6_plen = htons(ip6_psize); 278f08c3bdfSopenharmony_ci pkt.hdr.ip6_nxt = IPPROTO_HOPOPTS; 279f08c3bdfSopenharmony_ci pkt.hdr.ip6_hlim = 1; 280f08c3bdfSopenharmony_ci pkt.hdr.ip6_src = info_p->saddr; 281f08c3bdfSopenharmony_ci pkt.hdr.ip6_dst = info_p->daddr; 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ci /* Router Alert Option */ 284f08c3bdfSopenharmony_ci alart_p->nxthdr = IPPROTO_ICMPV6; 285f08c3bdfSopenharmony_ci alart_p->hbh_len = 0; 286f08c3bdfSopenharmony_ci alart_p->alart_type = 0x05; /* router alert */ 287f08c3bdfSopenharmony_ci alart_p->alart_len = 0x02; /* data len */ 288f08c3bdfSopenharmony_ci alart_p->alart_data = htons(0x0000); /* MLD */ 289f08c3bdfSopenharmony_ci alart_p->padn_type = 0x01; /* PadN option */ 290f08c3bdfSopenharmony_ci alart_p->padn_len = 0x00; /* 2 Octets */ 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci /* MLDv2 query */ 293f08c3bdfSopenharmony_ci query_p->type = MLD_LISTENER_QUERY; 294f08c3bdfSopenharmony_ci query_p->code = 0; 295f08c3bdfSopenharmony_ci query_p->cksum = 0; /* Calculate later */ 296f08c3bdfSopenharmony_ci query_p->maxdelay = htons(mrc); 297f08c3bdfSopenharmony_ci query_p->resv = 0; 298f08c3bdfSopenharmony_ci query_p->suppress = 0; 299f08c3bdfSopenharmony_ci query_p->qrv = 0; 300f08c3bdfSopenharmony_ci query_p->qqic = 0; 301f08c3bdfSopenharmony_ci query_p->nsrcs = htons(numsrc); 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_ci /* define the multicast address */ 304f08c3bdfSopenharmony_ci if (memcmp(&info_p->daddr, &in6addr_allnodes, sizeof(struct in6_addr)) 305f08c3bdfSopenharmony_ci == 0) 306f08c3bdfSopenharmony_ci query_p->addr = in6addr_any; 307f08c3bdfSopenharmony_ci else 308f08c3bdfSopenharmony_ci query_p->addr = info_p->daddr; 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci /* substitute source addresses */ 311f08c3bdfSopenharmony_ci sp = saddrs; 312f08c3bdfSopenharmony_ci for (idx = 0; idx < numsrc; idx++) { 313f08c3bdfSopenharmony_ci ep = strchr(sp, ','); 314f08c3bdfSopenharmony_ci if (ep != NULL) 315f08c3bdfSopenharmony_ci *ep = '\0'; 316f08c3bdfSopenharmony_ci if (debug) 317f08c3bdfSopenharmony_ci fprintf(stderr, "source address[%u]: %s\n", idx, sp); 318f08c3bdfSopenharmony_ci 319f08c3bdfSopenharmony_ci if (inet_pton(AF_INET6, sp, &ip6) <= 0) { 320f08c3bdfSopenharmony_ci fprintf(stderr, 321f08c3bdfSopenharmony_ci "source address list is something wrong\n"); 322f08c3bdfSopenharmony_ci return 1; 323f08c3bdfSopenharmony_ci } 324f08c3bdfSopenharmony_ci query_p->srcs[idx] = ip6; 325f08c3bdfSopenharmony_ci sp = ep + 1; 326f08c3bdfSopenharmony_ci } 327f08c3bdfSopenharmony_ci 328f08c3bdfSopenharmony_ci /* ICMPv6 Pseudo packet */ 329f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_src = pkt.hdr.ip6_src; 330f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_dst = pkt.hdr.ip6_dst; 331f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_plen = htons(query_size); 332f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_zero1 = 0; 333f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_zero2 = 0; 334f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_nxt = IPPROTO_ICMPV6; 335f08c3bdfSopenharmony_ci memcpy(pseudo.payload, query_p, query_size); 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci /* Calcualte checksums */ 338f08c3bdfSopenharmony_ci query_p->cksum = calc_checksum((u_int16_t *) (&pseudo), 339f08c3bdfSopenharmony_ci sizeof(struct pseudo_ip6_hdr) + 340f08c3bdfSopenharmony_ci query_size); 341f08c3bdfSopenharmony_ci 342f08c3bdfSopenharmony_ci /* Store the clean packet data */ 343f08c3bdfSopenharmony_ci info_p->pkt = pkt; 344f08c3bdfSopenharmony_ci info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize; 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_ci return 0; 347f08c3bdfSopenharmony_ci} 348f08c3bdfSopenharmony_ci 349f08c3bdfSopenharmony_ci/* 350f08c3bdfSopenharmony_ci * Function: create_echo_request() 351f08c3bdfSopenharmony_ci * 352f08c3bdfSopenharmony_ci * Description: 353f08c3bdfSopenharmony_ci * This function creates icmpv6 echo request 354f08c3bdfSopenharmony_ci * 355f08c3bdfSopenharmony_ci * Argument: 356f08c3bdfSopenharmony_ci * info_p: pointer to data of icmp structure 357f08c3bdfSopenharmony_ci * 358f08c3bdfSopenharmony_ci * Return value: 359f08c3bdfSopenharmony_ci * None 360f08c3bdfSopenharmony_ci */ 361f08c3bdfSopenharmony_civoid create_echo_request(struct icmp6_info *info_p) 362f08c3bdfSopenharmony_ci{ 363f08c3bdfSopenharmony_ci struct ip6_datagram pkt; /* ICMPv6 packet */ 364f08c3bdfSopenharmony_ci struct icmp6_segment *echoreq_p; /* Echo request header and payload */ 365f08c3bdfSopenharmony_ci struct pseudo_ip6_datagram pseudo; /* ICMPv6 pseudo packet for checksum */ 366f08c3bdfSopenharmony_ci unsigned short int ip6_psize; /* payload size */ 367f08c3bdfSopenharmony_ci 368f08c3bdfSopenharmony_ci ip6_psize = sizeof(struct icmp6_hdr) /* ICMP header */ 369f08c3bdfSopenharmony_ci +info_p->data_size; /* ICMP payload */ 370f08c3bdfSopenharmony_ci memset(&pkt, '\0', sizeof(struct ip6_datagram)); 371f08c3bdfSopenharmony_ci echoreq_p = (struct icmp6_segment *)&(pkt.payload); 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci /* IPv6 Header */ 374f08c3bdfSopenharmony_ci pkt.hdr.ip6_vfc = 6 << 4; 375f08c3bdfSopenharmony_ci pkt.hdr.ip6_flow |= 0; 376f08c3bdfSopenharmony_ci pkt.hdr.ip6_plen = htons(ip6_psize); 377f08c3bdfSopenharmony_ci pkt.hdr.ip6_nxt = IPPROTO_ICMPV6; 378f08c3bdfSopenharmony_ci pkt.hdr.ip6_hlim = IPV6_DEFAULT_HOPLIMIT; 379f08c3bdfSopenharmony_ci pkt.hdr.ip6_src = info_p->saddr; 380f08c3bdfSopenharmony_ci pkt.hdr.ip6_dst = info_p->daddr; 381f08c3bdfSopenharmony_ci 382f08c3bdfSopenharmony_ci /* Echo Request Header */ 383f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_type = ICMP6_ECHO_REQUEST; 384f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_code = 0; 385f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_cksum = 0; /* Calculate later */ 386f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_id = htons(ICMP_ECHO_ID); 387f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_seq = htons(1); 388f08c3bdfSopenharmony_ci 389f08c3bdfSopenharmony_ci /* Echo Request Payload */ 390f08c3bdfSopenharmony_ci fill_payload(echoreq_p->data, info_p->data_size); 391f08c3bdfSopenharmony_ci 392f08c3bdfSopenharmony_ci /* ICMPv6 Pseudo packet */ 393f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_src = pkt.hdr.ip6_src; 394f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_dst = pkt.hdr.ip6_dst; 395f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_plen = htons(ip6_psize); 396f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_zero1 = 0; 397f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_zero2 = 0; 398f08c3bdfSopenharmony_ci pseudo.hdr.p_ip6_nxt = IPPROTO_ICMPV6; 399f08c3bdfSopenharmony_ci memcpy(pseudo.payload, echoreq_p, ip6_psize); 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci /* Calcualte checksums */ 402f08c3bdfSopenharmony_ci echoreq_p->hdr.icmp6_cksum = calc_checksum((u_int16_t *) (&pseudo), 403f08c3bdfSopenharmony_ci sizeof(struct pseudo_ip6_hdr) 404f08c3bdfSopenharmony_ci + ip6_psize); 405f08c3bdfSopenharmony_ci 406f08c3bdfSopenharmony_ci /* Store the clean packet data */ 407f08c3bdfSopenharmony_ci info_p->pkt = pkt; 408f08c3bdfSopenharmony_ci info_p->pkt_size = sizeof(struct ip6_hdr) + ip6_psize; 409f08c3bdfSopenharmony_ci} 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci/* 412f08c3bdfSopenharmony_ci * Function: parse_options() 413f08c3bdfSopenharmony_ci * 414f08c3bdfSopenharmony_ci * Description: 415f08c3bdfSopenharmony_ci * This function parse the options 416f08c3bdfSopenharmony_ci * 417f08c3bdfSopenharmony_ci * Argument: 418f08c3bdfSopenharmony_ci * argc: the number of argument 419f08c3bdfSopenharmony_ci * argv: arguments 420f08c3bdfSopenharmony_ci * info_p: pointer to data of icmp data to modify 421f08c3bdfSopenharmony_ci * bg_p: pointer to the flag of working in backgrond 422f08c3bdfSopenharmony_ci * 423f08c3bdfSopenharmony_ci * Return value: 424f08c3bdfSopenharmony_ci * None 425f08c3bdfSopenharmony_ci */ 426f08c3bdfSopenharmony_civoid parse_options(int argc, char *argv[], struct icmp6_info *info_p, int *bg_p) 427f08c3bdfSopenharmony_ci{ 428f08c3bdfSopenharmony_ci int optc; /* option */ 429f08c3bdfSopenharmony_ci unsigned long opt_ul; /* option value in unsigned long */ 430f08c3bdfSopenharmony_ci double opt_d; /* option value in double */ 431f08c3bdfSopenharmony_ci struct in6_addr opt_addr; /* option value in struct in_addr */ 432f08c3bdfSopenharmony_ci struct sockaddr_ll opt_addr_ll; /* option value in struct sockaddr_ll */ 433f08c3bdfSopenharmony_ci char *ifname; /* interface name where datagrams go out */ 434f08c3bdfSopenharmony_ci int is_mld_query; /* set to non-zero if sending MLDv2 query */ 435f08c3bdfSopenharmony_ci char *mld_saddrs; /* comma separated array of source addresses */ 436f08c3bdfSopenharmony_ci uint16_t max_resp; /* Max Resp Code */ 437f08c3bdfSopenharmony_ci int is_specified_daddr_ll = 0; 438f08c3bdfSopenharmony_ci int is_specified_saddr = 0; 439f08c3bdfSopenharmony_ci int is_specified_daddr = 0; 440f08c3bdfSopenharmony_ci 441f08c3bdfSopenharmony_ci ifname = NULL; 442f08c3bdfSopenharmony_ci is_mld_query = 0; 443f08c3bdfSopenharmony_ci mld_saddrs = NULL; 444f08c3bdfSopenharmony_ci max_resp = MY_MLD_MAX_HOST_REPORT_DELAY; 445f08c3bdfSopenharmony_ci 446f08c3bdfSopenharmony_ci while ((optc = 447f08c3bdfSopenharmony_ci getopt(argc, argv, "I:S:M:D:t:w:obdhs:iLnvma:r:")) != EOF) { 448f08c3bdfSopenharmony_ci switch (optc) { 449f08c3bdfSopenharmony_ci case 'I': 450f08c3bdfSopenharmony_ci if (if_nametoindex(optarg) == 0) { 451f08c3bdfSopenharmony_ci fprintf(stderr, 452f08c3bdfSopenharmony_ci "specified interface is incorrect\n"); 453f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 454f08c3bdfSopenharmony_ci } 455f08c3bdfSopenharmony_ci ifname = strdup(optarg); 456f08c3bdfSopenharmony_ci if (ifname == NULL) 457f08c3bdfSopenharmony_ci fatal_error("strdup() failed."); 458f08c3bdfSopenharmony_ci break; 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci case 'S': 461f08c3bdfSopenharmony_ci if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { 462f08c3bdfSopenharmony_ci fprintf(stderr, "Source address is wrong\n"); 463f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 464f08c3bdfSopenharmony_ci } 465f08c3bdfSopenharmony_ci info_p->saddr = opt_addr; 466f08c3bdfSopenharmony_ci is_specified_saddr = 1; 467f08c3bdfSopenharmony_ci break; 468f08c3bdfSopenharmony_ci 469f08c3bdfSopenharmony_ci case 'M': 470f08c3bdfSopenharmony_ci if (eth_pton(AF_INET6, optarg, &opt_addr_ll)) { 471f08c3bdfSopenharmony_ci fprintf(stderr, 472f08c3bdfSopenharmony_ci "Destination MAC address is wrong\n"); 473f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 474f08c3bdfSopenharmony_ci } 475f08c3bdfSopenharmony_ci info_p->daddr_ll = opt_addr_ll; 476f08c3bdfSopenharmony_ci is_specified_daddr_ll = 1; 477f08c3bdfSopenharmony_ci break; 478f08c3bdfSopenharmony_ci 479f08c3bdfSopenharmony_ci case 'D': 480f08c3bdfSopenharmony_ci if (inet_pton(AF_INET6, optarg, &opt_addr) <= 0) { 481f08c3bdfSopenharmony_ci fprintf(stderr, 482f08c3bdfSopenharmony_ci "Destination address is wrong\n"); 483f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 484f08c3bdfSopenharmony_ci } 485f08c3bdfSopenharmony_ci info_p->daddr = opt_addr; 486f08c3bdfSopenharmony_ci is_specified_daddr = 1; 487f08c3bdfSopenharmony_ci break; 488f08c3bdfSopenharmony_ci 489f08c3bdfSopenharmony_ci case 't': 490f08c3bdfSopenharmony_ci opt_d = strtod(optarg, NULL); 491f08c3bdfSopenharmony_ci if (opt_d < 0.0) { 492f08c3bdfSopenharmony_ci fprintf(stderr, 493f08c3bdfSopenharmony_ci "Timeout should be positive value\n"); 494f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 495f08c3bdfSopenharmony_ci } 496f08c3bdfSopenharmony_ci info_p->timeout = opt_d; 497f08c3bdfSopenharmony_ci break; 498f08c3bdfSopenharmony_ci 499f08c3bdfSopenharmony_ci case 'w': 500f08c3bdfSopenharmony_ci if (strtotimespec(optarg, &info_p->interval)) { 501f08c3bdfSopenharmony_ci fprintf(stderr, 502f08c3bdfSopenharmony_ci "Interval is something wrong\n"); 503f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 504f08c3bdfSopenharmony_ci } 505f08c3bdfSopenharmony_ci break; 506f08c3bdfSopenharmony_ci 507f08c3bdfSopenharmony_ci case 'o': 508f08c3bdfSopenharmony_ci info_p->timeout = -1.0; 509f08c3bdfSopenharmony_ci break; 510f08c3bdfSopenharmony_ci 511f08c3bdfSopenharmony_ci case 'b': 512f08c3bdfSopenharmony_ci *bg_p = 1; 513f08c3bdfSopenharmony_ci break; 514f08c3bdfSopenharmony_ci 515f08c3bdfSopenharmony_ci case 'd': 516f08c3bdfSopenharmony_ci debug = 1; 517f08c3bdfSopenharmony_ci break; 518f08c3bdfSopenharmony_ci 519f08c3bdfSopenharmony_ci case 'h': 520f08c3bdfSopenharmony_ci usage(program_name, EXIT_SUCCESS); 521f08c3bdfSopenharmony_ci break; 522f08c3bdfSopenharmony_ci 523f08c3bdfSopenharmony_ci /* Options for echo request */ 524f08c3bdfSopenharmony_ci case 's': 525f08c3bdfSopenharmony_ci opt_ul = strtoul(optarg, NULL, 0); 526f08c3bdfSopenharmony_ci if (opt_ul > ICMPV6_DATA_MAXSIZE) { 527f08c3bdfSopenharmony_ci fprintf(stderr, 528f08c3bdfSopenharmony_ci "Data size sholud be less than %d\n", 529f08c3bdfSopenharmony_ci ICMPV6_DATA_MAXSIZE + 1); 530f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 531f08c3bdfSopenharmony_ci } 532f08c3bdfSopenharmony_ci info_p->data_size = opt_ul; 533f08c3bdfSopenharmony_ci break; 534f08c3bdfSopenharmony_ci 535f08c3bdfSopenharmony_ci /* Options for fake */ 536f08c3bdfSopenharmony_ci case 'i': 537f08c3bdfSopenharmony_ci info_p->fake_flag |= FAKE_DADDR; 538f08c3bdfSopenharmony_ci break; 539f08c3bdfSopenharmony_ci 540f08c3bdfSopenharmony_ci case 'L': 541f08c3bdfSopenharmony_ci info_p->fake_flag |= FAKE_PLEN; 542f08c3bdfSopenharmony_ci break; 543f08c3bdfSopenharmony_ci 544f08c3bdfSopenharmony_ci case 'n': 545f08c3bdfSopenharmony_ci info_p->fake_flag |= FAKE_NXT; 546f08c3bdfSopenharmony_ci break; 547f08c3bdfSopenharmony_ci 548f08c3bdfSopenharmony_ci case 'v': 549f08c3bdfSopenharmony_ci info_p->fake_flag |= FAKE_VERSION; 550f08c3bdfSopenharmony_ci break; 551f08c3bdfSopenharmony_ci 552f08c3bdfSopenharmony_ci /* Options for MLDv2 query */ 553f08c3bdfSopenharmony_ci case 'm': 554f08c3bdfSopenharmony_ci is_mld_query = 1; 555f08c3bdfSopenharmony_ci break; 556f08c3bdfSopenharmony_ci 557f08c3bdfSopenharmony_ci case 'a': 558f08c3bdfSopenharmony_ci mld_saddrs = strdup(optarg); 559f08c3bdfSopenharmony_ci if (mld_saddrs == NULL) 560f08c3bdfSopenharmony_ci fatal_error("strdup()"); 561f08c3bdfSopenharmony_ci break; 562f08c3bdfSopenharmony_ci 563f08c3bdfSopenharmony_ci case 'r': 564f08c3bdfSopenharmony_ci opt_ul = strtoul(optarg, NULL, 0); 565f08c3bdfSopenharmony_ci if (opt_ul > 0xFFFF) { 566f08c3bdfSopenharmony_ci fprintf(stderr, 567f08c3bdfSopenharmony_ci "Max Resp Code should be less than 65536\n"); 568f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 569f08c3bdfSopenharmony_ci } 570f08c3bdfSopenharmony_ci max_resp = opt_ul; 571f08c3bdfSopenharmony_ci break; 572f08c3bdfSopenharmony_ci 573f08c3bdfSopenharmony_ci default: 574f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 575f08c3bdfSopenharmony_ci } 576f08c3bdfSopenharmony_ci } 577f08c3bdfSopenharmony_ci 578f08c3bdfSopenharmony_ci if (ifname == NULL) { 579f08c3bdfSopenharmony_ci fprintf(stderr, "Outgoing interface is not specified\n"); 580f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 581f08c3bdfSopenharmony_ci } 582f08c3bdfSopenharmony_ci specify_hw_addr(&info_p->saddr_ll, ifname); 583f08c3bdfSopenharmony_ci 584f08c3bdfSopenharmony_ci if (!is_specified_saddr) { 585f08c3bdfSopenharmony_ci fprintf(stderr, "Source IP address is not specified\n"); 586f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 587f08c3bdfSopenharmony_ci } 588f08c3bdfSopenharmony_ci 589f08c3bdfSopenharmony_ci if (is_mld_query) { /* MLDv2 query */ 590f08c3bdfSopenharmony_ci if (info_p->fake_flag) { 591f08c3bdfSopenharmony_ci fprintf(stderr, 592f08c3bdfSopenharmony_ci "It is not permitted to break MLDv2 query\n"); 593f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 594f08c3bdfSopenharmony_ci } 595f08c3bdfSopenharmony_ci 596f08c3bdfSopenharmony_ci if (!is_specified_daddr) 597f08c3bdfSopenharmony_ci info_p->daddr = in6addr_allnodes; 598f08c3bdfSopenharmony_ci 599f08c3bdfSopenharmony_ci calc_hd_mcastaddr(&info_p->daddr_ll, &info_p->daddr); 600f08c3bdfSopenharmony_ci if (create_mld_query(info_p, max_resp, mld_saddrs)) 601f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 602f08c3bdfSopenharmony_ci } else { /* echo request */ 603f08c3bdfSopenharmony_ci if (info_p->fake_flag) 604f08c3bdfSopenharmony_ci srand(getpid()); 605f08c3bdfSopenharmony_ci 606f08c3bdfSopenharmony_ci if (!is_specified_daddr_ll) { 607f08c3bdfSopenharmony_ci fprintf(stderr, 608f08c3bdfSopenharmony_ci "Destination MAC address is not specified\n"); 609f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 610f08c3bdfSopenharmony_ci } 611f08c3bdfSopenharmony_ci 612f08c3bdfSopenharmony_ci if (!is_specified_daddr) { 613f08c3bdfSopenharmony_ci fprintf(stderr, 614f08c3bdfSopenharmony_ci "Destination IP address is not specified\n"); 615f08c3bdfSopenharmony_ci usage(program_name, EXIT_FAILURE); 616f08c3bdfSopenharmony_ci } 617f08c3bdfSopenharmony_ci 618f08c3bdfSopenharmony_ci create_echo_request(info_p); 619f08c3bdfSopenharmony_ci } 620f08c3bdfSopenharmony_ci info_p->daddr_ll.sll_ifindex = if_nametoindex(ifname); 621f08c3bdfSopenharmony_ci} 622f08c3bdfSopenharmony_ci 623f08c3bdfSopenharmony_ci/* 624f08c3bdfSopenharmony_ci * Function: thrust_fakes() 625f08c3bdfSopenharmony_ci * 626f08c3bdfSopenharmony_ci * Description: 627f08c3bdfSopenharmony_ci * This function thrust fake information to the icmp packet 628f08c3bdfSopenharmony_ci * 629f08c3bdfSopenharmony_ci * Argument: 630f08c3bdfSopenharmony_ci * pkt : Payload of the Ethernet frame (Namely, IPv6 packet) 631f08c3bdfSopenharmony_ci * fake_flag: Flag which represents what information would be faked 632f08c3bdfSopenharmony_ci * 633f08c3bdfSopenharmony_ci * Return value: 634f08c3bdfSopenharmony_ci * None 635f08c3bdfSopenharmony_ci */ 636f08c3bdfSopenharmony_civoid thrust_fakes(struct ip6_datagram *pkt, u_int16_t fake_flag) 637f08c3bdfSopenharmony_ci{ 638f08c3bdfSopenharmony_ci int rand_val; 639f08c3bdfSopenharmony_ci size_t bitsize; 640f08c3bdfSopenharmony_ci u_int32_t seed; 641f08c3bdfSopenharmony_ci 642f08c3bdfSopenharmony_ci if (debug) 643f08c3bdfSopenharmony_ci fprintf(stderr, "fake_flag = %2x\n", fake_flag); 644f08c3bdfSopenharmony_ci 645f08c3bdfSopenharmony_ci if (fake_flag & FAKE_VERSION) { /* version */ 646f08c3bdfSopenharmony_ci bitsize = 4; 647f08c3bdfSopenharmony_ci seed = bit_change_seed(bitsize, 1); 648f08c3bdfSopenharmony_ci pkt->hdr.ip6_vfc ^= (seed << 4); 649f08c3bdfSopenharmony_ci } 650f08c3bdfSopenharmony_ci 651f08c3bdfSopenharmony_ci if (fake_flag & FAKE_PLEN) { /* total length */ 652f08c3bdfSopenharmony_ci bitsize = sizeof(pkt->hdr.ip6_plen) * 8; 653f08c3bdfSopenharmony_ci seed = bit_change_seed(bitsize, bitsize / 8); 654f08c3bdfSopenharmony_ci pkt->hdr.ip6_plen ^= seed; 655f08c3bdfSopenharmony_ci } 656f08c3bdfSopenharmony_ci 657f08c3bdfSopenharmony_ci if (fake_flag & FAKE_NXT) { /* next header */ 658f08c3bdfSopenharmony_ci rand_val = rand() / ((RAND_MAX + 1U) / 5); 659f08c3bdfSopenharmony_ci switch (rand_val) { 660f08c3bdfSopenharmony_ci case 1: 661f08c3bdfSopenharmony_ci case 2: 662f08c3bdfSopenharmony_ci if (debug) 663f08c3bdfSopenharmony_ci fprintf(stderr, "Bit reverse\n"); 664f08c3bdfSopenharmony_ci bitsize = sizeof(pkt->hdr.ip6_nxt) * 8; 665f08c3bdfSopenharmony_ci seed = bit_change_seed(bitsize, 0); 666f08c3bdfSopenharmony_ci pkt->hdr.ip6_nxt ^= seed; 667f08c3bdfSopenharmony_ci break; 668f08c3bdfSopenharmony_ci 669f08c3bdfSopenharmony_ci case 3: 670f08c3bdfSopenharmony_ci case 4: 671f08c3bdfSopenharmony_ci if (debug) 672f08c3bdfSopenharmony_ci fprintf(stderr, "Unknown Protocol\n"); 673f08c3bdfSopenharmony_ci if (rand_val) { 674f08c3bdfSopenharmony_ci int number; 675f08c3bdfSopenharmony_ci int counter; 676f08c3bdfSopenharmony_ci for (counter = 0; counter <= 0xff; counter++) { 677f08c3bdfSopenharmony_ci number = 678f08c3bdfSopenharmony_ci rand() / ((RAND_MAX + 1U) / 0x100); 679f08c3bdfSopenharmony_ci if (getprotobynumber(number) == NULL) { 680f08c3bdfSopenharmony_ci pkt->hdr.ip6_nxt = number; 681f08c3bdfSopenharmony_ci break; 682f08c3bdfSopenharmony_ci } 683f08c3bdfSopenharmony_ci } 684f08c3bdfSopenharmony_ci } 685f08c3bdfSopenharmony_ci break; 686f08c3bdfSopenharmony_ci 687f08c3bdfSopenharmony_ci default: 688f08c3bdfSopenharmony_ci if (debug) 689f08c3bdfSopenharmony_ci fprintf(stderr, "Do nothing\n"); 690f08c3bdfSopenharmony_ci break; 691f08c3bdfSopenharmony_ci } 692f08c3bdfSopenharmony_ci } 693f08c3bdfSopenharmony_ci 694f08c3bdfSopenharmony_ci if (fake_flag & FAKE_DADDR) { /* destination address */ 695f08c3bdfSopenharmony_ci rand_val = rand() / ((RAND_MAX + 1U) / 4); 696f08c3bdfSopenharmony_ci bitsize = sizeof(pkt->hdr.ip6_dst.s6_addr32[rand_val]) * 8; 697f08c3bdfSopenharmony_ci seed = bit_change_seed(bitsize, bitsize / 8); 698f08c3bdfSopenharmony_ci pkt->hdr.ip6_dst.s6_addr32[rand_val] ^= seed; 699f08c3bdfSopenharmony_ci } 700f08c3bdfSopenharmony_ci} 701f08c3bdfSopenharmony_ci 702f08c3bdfSopenharmony_ci/* 703f08c3bdfSopenharmony_ci * Function: send_packet() 704f08c3bdfSopenharmony_ci * 705f08c3bdfSopenharmony_ci * Description: 706f08c3bdfSopenharmony_ci * This function sends icmpv6 packet 707f08c3bdfSopenharmony_ci * 708f08c3bdfSopenharmony_ci * Argument: 709f08c3bdfSopenharmony_ci * info_p: pointer to data of icmp structure 710f08c3bdfSopenharmony_ci * 711f08c3bdfSopenharmony_ci * Return value: 712f08c3bdfSopenharmony_ci * None 713f08c3bdfSopenharmony_ci */ 714f08c3bdfSopenharmony_civoid send_packets(struct icmp6_info *info_p) 715f08c3bdfSopenharmony_ci{ 716f08c3bdfSopenharmony_ci int sock_fd; 717f08c3bdfSopenharmony_ci int retval; 718f08c3bdfSopenharmony_ci struct ip6_datagram pkt; 719f08c3bdfSopenharmony_ci double start_time; 720f08c3bdfSopenharmony_ci 721f08c3bdfSopenharmony_ci /* Open a socket */ 722f08c3bdfSopenharmony_ci sock_fd = socket(AF_PACKET, SOCK_DGRAM, htons(ETH_P_IPV6)); 723f08c3bdfSopenharmony_ci if (sock_fd < 0) 724f08c3bdfSopenharmony_ci fatal_error("socket()"); 725f08c3bdfSopenharmony_ci 726f08c3bdfSopenharmony_ci /* Bind the socket to the physical address */ 727f08c3bdfSopenharmony_ci retval = bind(sock_fd, (struct sockaddr *)&(info_p->saddr_ll), 728f08c3bdfSopenharmony_ci sizeof(struct sockaddr_ll)); 729f08c3bdfSopenharmony_ci if (retval < 0) 730f08c3bdfSopenharmony_ci fatal_error("bind()"); 731f08c3bdfSopenharmony_ci 732f08c3bdfSopenharmony_ci /* Set singal hander for SIGHUP */ 733f08c3bdfSopenharmony_ci handler.sa_handler = set_signal_flag; 734f08c3bdfSopenharmony_ci handler.sa_flags = 0; 735f08c3bdfSopenharmony_ci if (sigfillset(&handler.sa_mask) < 0) 736f08c3bdfSopenharmony_ci fatal_error("sigfillset()"); 737f08c3bdfSopenharmony_ci if (sigaction(SIGHUP, &handler, NULL) < 0) 738f08c3bdfSopenharmony_ci fatal_error("sigfillset()"); 739f08c3bdfSopenharmony_ci 740f08c3bdfSopenharmony_ci /* 741f08c3bdfSopenharmony_ci * loop for sending packets 742f08c3bdfSopenharmony_ci */ 743f08c3bdfSopenharmony_ci pkt = info_p->pkt; 744f08c3bdfSopenharmony_ci start_time = time(NULL); 745f08c3bdfSopenharmony_ci 746f08c3bdfSopenharmony_ci for (;;) { 747f08c3bdfSopenharmony_ci if (info_p->fake_flag) { 748f08c3bdfSopenharmony_ci pkt = info_p->pkt; 749f08c3bdfSopenharmony_ci thrust_fakes(&pkt, info_p->fake_flag); 750f08c3bdfSopenharmony_ci } 751f08c3bdfSopenharmony_ci 752f08c3bdfSopenharmony_ci retval = sendto(sock_fd, &pkt, info_p->pkt_size, 0, 753f08c3bdfSopenharmony_ci (struct sockaddr *)&(info_p->daddr_ll), 754f08c3bdfSopenharmony_ci sizeof(struct sockaddr_ll)); 755f08c3bdfSopenharmony_ci if (retval < 0) 756f08c3bdfSopenharmony_ci fatal_error("sendto()"); 757f08c3bdfSopenharmony_ci 758f08c3bdfSopenharmony_ci /* Check timeout: 759f08c3bdfSopenharmony_ci If timeout value is negative only send one datagram */ 760f08c3bdfSopenharmony_ci if (info_p->timeout) 761f08c3bdfSopenharmony_ci if (info_p->timeout < difftime(time(NULL), start_time)) 762f08c3bdfSopenharmony_ci break; 763f08c3bdfSopenharmony_ci 764f08c3bdfSopenharmony_ci /* Wait in specified interval */ 765f08c3bdfSopenharmony_ci nanosleep(&info_p->interval, NULL); 766f08c3bdfSopenharmony_ci 767f08c3bdfSopenharmony_ci if (catch_sighup) /* catch SIGHUP */ 768f08c3bdfSopenharmony_ci break; 769f08c3bdfSopenharmony_ci } 770f08c3bdfSopenharmony_ci 771f08c3bdfSopenharmony_ci /* Close the socket */ 772f08c3bdfSopenharmony_ci close(sock_fd); 773f08c3bdfSopenharmony_ci} 774f08c3bdfSopenharmony_ci 775f08c3bdfSopenharmony_ci/* 776f08c3bdfSopenharmony_ci * 777f08c3bdfSopenharmony_ci * Function: main() 778f08c3bdfSopenharmony_ci * 779f08c3bdfSopenharmony_ci */ 780f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 781f08c3bdfSopenharmony_ci{ 782f08c3bdfSopenharmony_ci struct icmp6_info icmp6_data; 783f08c3bdfSopenharmony_ci int background = 0; 784f08c3bdfSopenharmony_ci 785f08c3bdfSopenharmony_ci debug = 0; 786f08c3bdfSopenharmony_ci program_name = strdup(argv[0]); 787f08c3bdfSopenharmony_ci 788f08c3bdfSopenharmony_ci memset(&icmp6_data, '\0', sizeof(struct icmp6_info)); 789f08c3bdfSopenharmony_ci parse_options(argc, argv, &icmp6_data, &background); 790f08c3bdfSopenharmony_ci 791f08c3bdfSopenharmony_ci if (background) /* Work in the background */ 792f08c3bdfSopenharmony_ci if (daemon(0, 0) < 0) 793f08c3bdfSopenharmony_ci fatal_error("daemon()"); 794f08c3bdfSopenharmony_ci 795f08c3bdfSopenharmony_ci send_packets(&icmp6_data); 796f08c3bdfSopenharmony_ci 797f08c3bdfSopenharmony_ci exit(EXIT_SUCCESS); 798f08c3bdfSopenharmony_ci} 799