1f08c3bdfSopenharmony_ci/******************************************************************************/ 2f08c3bdfSopenharmony_ci/* */ 3f08c3bdfSopenharmony_ci/* Copyright (c) International Business Machines Corp., 2005, 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-common.c 24f08c3bdfSopenharmony_ci * 25f08c3bdfSopenharmony_ci * Description: 26f08c3bdfSopenharmony_ci * Common functions and variables in the ns-tools 27f08c3bdfSopenharmony_ci * 28f08c3bdfSopenharmony_ci * Author: 29f08c3bdfSopenharmony_ci * Mitsuru Chinen <mitch@jp.ibm.com> 30f08c3bdfSopenharmony_ci * 31f08c3bdfSopenharmony_ci * History: 32f08c3bdfSopenharmony_ci * Oct 19 2005 - Created (Mitsuru Chinen) 33f08c3bdfSopenharmony_ci * May 1 2006 - Added functions for broken_ip, route, multicast tests 34f08c3bdfSopenharmony_ci *---------------------------------------------------------------------------*/ 35f08c3bdfSopenharmony_ci 36f08c3bdfSopenharmony_ci/* 37f08c3bdfSopenharmony_ci * Fixed values 38f08c3bdfSopenharmony_ci */ 39f08c3bdfSopenharmony_ci#define PROC_RMEM_MAX "/proc/sys/net/core/rmem_max" 40f08c3bdfSopenharmony_ci#define PROC_WMEM_MAX "/proc/sys/net/core/wmem_max" 41f08c3bdfSopenharmony_ci 42f08c3bdfSopenharmony_ci/* 43f08c3bdfSopenharmony_ci * Standard Header Files 44f08c3bdfSopenharmony_ci */ 45f08c3bdfSopenharmony_ci#include <stdio.h> 46f08c3bdfSopenharmony_ci#include <stdlib.h> 47f08c3bdfSopenharmony_ci#include <string.h> 48f08c3bdfSopenharmony_ci#include <sys/ioctl.h> 49f08c3bdfSopenharmony_ci#include <sys/types.h> 50f08c3bdfSopenharmony_ci#include <sys/socket.h> 51f08c3bdfSopenharmony_ci#include <net/ethernet.h> 52f08c3bdfSopenharmony_ci#include <net/if.h> 53f08c3bdfSopenharmony_ci#include <net/if_arp.h> 54f08c3bdfSopenharmony_ci 55f08c3bdfSopenharmony_ci#include "ns-mcast.h" 56f08c3bdfSopenharmony_ci#define NS_COMMON 1 57f08c3bdfSopenharmony_ci#include "ns-traffic.h" 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci/* 60f08c3bdfSopenharmony_ci * Function: fatal_error() 61f08c3bdfSopenharmony_ci * 62f08c3bdfSopenharmony_ci * Description: 63f08c3bdfSopenharmony_ci * Output an error message then exit the program with EXIT_FAILURE 64f08c3bdfSopenharmony_ci * 65f08c3bdfSopenharmony_ci * Argument: 66f08c3bdfSopenharmony_ci * errmsg: message printed by perror() 67f08c3bdfSopenharmony_ci * 68f08c3bdfSopenharmony_ci * Return value: 69f08c3bdfSopenharmony_ci * This function does not return. 70f08c3bdfSopenharmony_ci */ 71f08c3bdfSopenharmony_civoid fatal_error(char *errmsg) 72f08c3bdfSopenharmony_ci{ 73f08c3bdfSopenharmony_ci perror(errmsg); 74f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 75f08c3bdfSopenharmony_ci} 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_ci/* 78f08c3bdfSopenharmony_ci * Function: maximize_sockbuf() 79f08c3bdfSopenharmony_ci * 80f08c3bdfSopenharmony_ci * Descripton: 81f08c3bdfSopenharmony_ci * This function maximize the send and receive buffer size of a socket 82f08c3bdfSopenharmony_ci * 83f08c3bdfSopenharmony_ci * Argument: 84f08c3bdfSopenharmony_ci * sd: target socket descriptor 85f08c3bdfSopenharmony_ci * 86f08c3bdfSopenharmony_ci * Return value: 87f08c3bdfSopenharmony_ci * None 88f08c3bdfSopenharmony_ci */ 89f08c3bdfSopenharmony_civoid maximize_sockbuf(int sd) 90f08c3bdfSopenharmony_ci{ 91f08c3bdfSopenharmony_ci size_t idx; 92f08c3bdfSopenharmony_ci int level[] = { SO_RCVBUF, SO_SNDBUF }; 93f08c3bdfSopenharmony_ci char *procfile[] = { PROC_RMEM_MAX, PROC_WMEM_MAX }; 94f08c3bdfSopenharmony_ci char *bufname[] = { "rcvbuf", "sndbuf" }; 95f08c3bdfSopenharmony_ci 96f08c3bdfSopenharmony_ci for (idx = 0; idx < (sizeof(level) / sizeof(int)); idx++) { 97f08c3bdfSopenharmony_ci FILE *fp; /* File pointer to a proc file */ 98f08c3bdfSopenharmony_ci int bufsiz; /* buffer size of socket */ 99f08c3bdfSopenharmony_ci unsigned int optlen; /* size of sd option parameter */ 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci if ((fp = fopen(procfile[idx], "r")) == NULL) { 102f08c3bdfSopenharmony_ci fprintf(stderr, "Failed to open %s\n", procfile[idx]); 103f08c3bdfSopenharmony_ci fatal_error("fopen()"); 104f08c3bdfSopenharmony_ci } 105f08c3bdfSopenharmony_ci if ((fscanf(fp, "%d", &bufsiz)) != 1) { 106f08c3bdfSopenharmony_ci fprintf(stderr, "Failed to read from %s\n", 107f08c3bdfSopenharmony_ci procfile[idx]); 108f08c3bdfSopenharmony_ci fatal_error("fscanf()"); 109f08c3bdfSopenharmony_ci } 110f08c3bdfSopenharmony_ci if (setsockopt 111f08c3bdfSopenharmony_ci (sd, SOL_SOCKET, level[idx], &bufsiz, sizeof(int))) { 112f08c3bdfSopenharmony_ci fatal_error("setsockopt()"); 113f08c3bdfSopenharmony_ci } 114f08c3bdfSopenharmony_ci if (fclose(fp)) { 115f08c3bdfSopenharmony_ci fprintf(stderr, "Failed to close to %s\n", 116f08c3bdfSopenharmony_ci procfile[idx]); 117f08c3bdfSopenharmony_ci fatal_error("fopen()"); 118f08c3bdfSopenharmony_ci } 119f08c3bdfSopenharmony_ci 120f08c3bdfSopenharmony_ci if (debug) { 121f08c3bdfSopenharmony_ci optlen = sizeof(bufsiz); 122f08c3bdfSopenharmony_ci if (getsockopt 123f08c3bdfSopenharmony_ci (sd, SOL_SOCKET, level[idx], &bufsiz, 124f08c3bdfSopenharmony_ci &optlen) < 0) { 125f08c3bdfSopenharmony_ci fatal_error("getsockopt()"); 126f08c3bdfSopenharmony_ci } 127f08c3bdfSopenharmony_ci fprintf(stderr, "socket %s size is %d\n", bufname[idx], 128f08c3bdfSopenharmony_ci bufsiz); 129f08c3bdfSopenharmony_ci } 130f08c3bdfSopenharmony_ci } 131f08c3bdfSopenharmony_ci} 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_ci/* 134f08c3bdfSopenharmony_ci * Function: calc_checksum() 135f08c3bdfSopenharmony_ci * 136f08c3bdfSopenharmony_ci * Description: 137f08c3bdfSopenharmony_ci * This function calculate the checksum of IPv4 or ICMP 138f08c3bdfSopenharmony_ci * 139f08c3bdfSopenharmony_ci * Argument: 140f08c3bdfSopenharmony_ci * data: pointer to target data for checksum 141f08c3bdfSopenharmony_ci * size: target data size 142f08c3bdfSopenharmony_ci * 143f08c3bdfSopenharmony_ci * Return value: 144f08c3bdfSopenharmony_ci * None 145f08c3bdfSopenharmony_ci */ 146f08c3bdfSopenharmony_ciu_int16_t calc_checksum(u_int16_t * data, size_t size) 147f08c3bdfSopenharmony_ci{ 148f08c3bdfSopenharmony_ci u_int32_t sum; 149f08c3bdfSopenharmony_ci u_int16_t *pos; 150f08c3bdfSopenharmony_ci size_t rest; 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci sum = 0; 153f08c3bdfSopenharmony_ci pos = data; 154f08c3bdfSopenharmony_ci for (rest = size; rest > 1; rest -= 2) 155f08c3bdfSopenharmony_ci sum += *(pos++); 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci if (rest > 0) 158f08c3bdfSopenharmony_ci sum += (*pos) & 0xff00; 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 161f08c3bdfSopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 162f08c3bdfSopenharmony_ci sum = ~sum; 163f08c3bdfSopenharmony_ci 164f08c3bdfSopenharmony_ci return sum; 165f08c3bdfSopenharmony_ci} 166f08c3bdfSopenharmony_ci 167f08c3bdfSopenharmony_ci/* 168f08c3bdfSopenharmony_ci * Function: fill_payload() 169f08c3bdfSopenharmony_ci * 170f08c3bdfSopenharmony_ci * Description: 171f08c3bdfSopenharmony_ci * This function fills the payload 172f08c3bdfSopenharmony_ci * 173f08c3bdfSopenharmony_ci * Argument: 174f08c3bdfSopenharmony_ci * payload_p: pointer to data of payload 175f08c3bdfSopenharmony_ci * size: payload size 176f08c3bdfSopenharmony_ci * 177f08c3bdfSopenharmony_ci * Return value: 178f08c3bdfSopenharmony_ci * None 179f08c3bdfSopenharmony_ci */ 180f08c3bdfSopenharmony_civoid fill_payload(unsigned char *payload_p, size_t size) 181f08c3bdfSopenharmony_ci{ 182f08c3bdfSopenharmony_ci size_t idx; 183f08c3bdfSopenharmony_ci 184f08c3bdfSopenharmony_ci for (idx = 0; idx < size; idx++) 185f08c3bdfSopenharmony_ci *(payload_p + idx) = idx % 0x100; 186f08c3bdfSopenharmony_ci} 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci/* 189f08c3bdfSopenharmony_ci * Function: rand_within() 190f08c3bdfSopenharmony_ci * 191f08c3bdfSopenharmony_ci * Description: 192f08c3bdfSopenharmony_ci * This function returns a presudo-random integer within specified range 193f08c3bdfSopenharmony_ci * 194f08c3bdfSopenharmony_ci * Argument: 195f08c3bdfSopenharmony_ci * first: Fisrt value of the range. If negative, assumed 0 196f08c3bdfSopenharmony_ci * last : Last value of the range. If bigger than RAND_MAX, assumed RAND_MAX 197f08c3bdfSopenharmony_ci * 198f08c3bdfSopenharmony_ci * Return value: 199f08c3bdfSopenharmony_ci * integer value between first to last 200f08c3bdfSopenharmony_ci */ 201f08c3bdfSopenharmony_ciint rand_within(int first, int last) 202f08c3bdfSopenharmony_ci{ 203f08c3bdfSopenharmony_ci unsigned int num; 204f08c3bdfSopenharmony_ci int rand_val; 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci first = first < 0 ? 0 : first; 207f08c3bdfSopenharmony_ci last = RAND_MAX < (unsigned int)last ? RAND_MAX : last; 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci num = last - first + 1U; 210f08c3bdfSopenharmony_ci rand_val = rand() / ((RAND_MAX + 1U) / num) + first; 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci return rand_val; 213f08c3bdfSopenharmony_ci} 214f08c3bdfSopenharmony_ci 215f08c3bdfSopenharmony_ci/* 216f08c3bdfSopenharmony_ci * Function: bit_change_seed 217f08c3bdfSopenharmony_ci * 218f08c3bdfSopenharmony_ci * Description: 219f08c3bdfSopenharmony_ci * This function creates a seed to change 1 bit at random position 220f08c3bdfSopenharmony_ci * 221f08c3bdfSopenharmony_ci * Argument: 222f08c3bdfSopenharmony_ci * bitsize : bit size of data whose bit would be changed 223f08c3bdfSopenharmony_ci * oversize: This value controls whether a bit is changed or not 224f08c3bdfSopenharmony_ci * 225f08c3bdfSopenharmony_ci * Return value: 226f08c3bdfSopenharmony_ci * seed of the bit for change. 227f08c3bdfSopenharmony_ci */ 228f08c3bdfSopenharmony_ciu_int32_t bit_change_seed(size_t bitsize, size_t oversize) 229f08c3bdfSopenharmony_ci{ 230f08c3bdfSopenharmony_ci int rand_val; 231f08c3bdfSopenharmony_ci u_int32_t seed; 232f08c3bdfSopenharmony_ci rand_val = rand() / ((RAND_MAX + 1U) / (bitsize + oversize)); 233f08c3bdfSopenharmony_ci 234f08c3bdfSopenharmony_ci seed = (rand_val < bitsize) ? (0x00000001 << rand_val) : 0; 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci if (debug) 237f08c3bdfSopenharmony_ci fprintf(stderr, "Bit seed is %08x\n", seed); 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci return seed; 240f08c3bdfSopenharmony_ci} 241f08c3bdfSopenharmony_ci 242f08c3bdfSopenharmony_ci/* 243f08c3bdfSopenharmony_ci * Function: eth_pton() 244f08c3bdfSopenharmony_ci * 245f08c3bdfSopenharmony_ci * Description: 246f08c3bdfSopenharmony_ci * This function convert a string to struct sockaddr_ll (Ethernet) 247f08c3bdfSopenharmony_ci * Note) The ifindex is set to `any'. 248f08c3bdfSopenharmony_ci * 249f08c3bdfSopenharmony_ci * Argument: 250f08c3bdfSopenharmony_ci * af : AF_INET or AF_INET6 251f08c3bdfSopenharmony_ci * str: Pointer to a string which represents MAC address 252f08c3bdfSopenharmony_ci * ll : pointer to struct sockaddr_ll 253f08c3bdfSopenharmony_ci * 254f08c3bdfSopenharmony_ci * Return value: 255f08c3bdfSopenharmony_ci * 0 : Success 256f08c3bdfSopenharmony_ci * 1 : Fail 257f08c3bdfSopenharmony_ci */ 258f08c3bdfSopenharmony_ciint eth_pton(int af, const char *str, struct sockaddr_ll *ll) 259f08c3bdfSopenharmony_ci{ 260f08c3bdfSopenharmony_ci size_t idx; 261f08c3bdfSopenharmony_ci unsigned char *addr_p; 262f08c3bdfSopenharmony_ci unsigned int val[ETH_ALEN]; 263f08c3bdfSopenharmony_ci 264f08c3bdfSopenharmony_ci ll->sll_family = AF_PACKET; /* Always AF_PACKET */ 265f08c3bdfSopenharmony_ci if (af == AF_INET) 266f08c3bdfSopenharmony_ci ll->sll_protocol = htons(ETH_P_IP); /* IPv4 */ 267f08c3bdfSopenharmony_ci else 268f08c3bdfSopenharmony_ci ll->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 269f08c3bdfSopenharmony_ci ll->sll_ifindex = 0; /* any interface */ 270f08c3bdfSopenharmony_ci ll->sll_hatype = ARPHRD_ETHER; /* Header type */ 271f08c3bdfSopenharmony_ci ll->sll_pkttype = PACKET_OTHERHOST; /* Packet type */ 272f08c3bdfSopenharmony_ci ll->sll_halen = ETH_ALEN; /* Length of address */ 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci /* Physical layer address */ 275f08c3bdfSopenharmony_ci if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", &val[0], &val[1], 276f08c3bdfSopenharmony_ci &val[2], &val[3], &val[4], &val[5]) != ETH_ALEN) { 277f08c3bdfSopenharmony_ci fprintf(stderr, "%s is not a valid MAC address", str); 278f08c3bdfSopenharmony_ci return 1; 279f08c3bdfSopenharmony_ci } 280f08c3bdfSopenharmony_ci 281f08c3bdfSopenharmony_ci addr_p = (unsigned char *)ll->sll_addr; 282f08c3bdfSopenharmony_ci for (idx = 0; idx < ETH_ALEN; idx++) 283f08c3bdfSopenharmony_ci addr_p[idx] = val[idx]; 284f08c3bdfSopenharmony_ci 285f08c3bdfSopenharmony_ci return 0; 286f08c3bdfSopenharmony_ci} 287f08c3bdfSopenharmony_ci 288f08c3bdfSopenharmony_ci/* 289f08c3bdfSopenharmony_ci * Function: get_ifinfo() 290f08c3bdfSopenharmony_ci * 291f08c3bdfSopenharmony_ci * Description: 292f08c3bdfSopenharmony_ci * This function gets the interface information with ioctl() 293f08c3bdfSopenharmony_ci * 294f08c3bdfSopenharmony_ci * Argument: 295f08c3bdfSopenharmony_ci * ans : ifreq structure to store the information 296f08c3bdfSopenharmony_ci * sock_fd : socket file descriptor 297f08c3bdfSopenharmony_ci * ifname : interface name 298f08c3bdfSopenharmony_ci * query : ioctl request value 299f08c3bdfSopenharmony_ci * 300f08c3bdfSopenharmony_ci * Return value: 301f08c3bdfSopenharmony_ci * None 302f08c3bdfSopenharmony_ci * 303f08c3bdfSopenharmony_ci */ 304f08c3bdfSopenharmony_civoid get_ifinfo(struct ifreq *ans, int sock_fd, const char *ifname, int query) 305f08c3bdfSopenharmony_ci{ 306f08c3bdfSopenharmony_ci memset(ans, '\0', sizeof(struct ifreq)); 307f08c3bdfSopenharmony_ci strncpy(ans->ifr_name, ifname, (IFNAMSIZ - 1)); 308f08c3bdfSopenharmony_ci 309f08c3bdfSopenharmony_ci if (ioctl(sock_fd, query, ans) < 0) 310f08c3bdfSopenharmony_ci fatal_error("ioctl()"); 311f08c3bdfSopenharmony_ci} 312f08c3bdfSopenharmony_ci 313f08c3bdfSopenharmony_ci/* 314f08c3bdfSopenharmony_ci * Function: strtotimespec() 315f08c3bdfSopenharmony_ci * 316f08c3bdfSopenharmony_ci * Description: 317f08c3bdfSopenharmony_ci * This function converts a string to timespec structure 318f08c3bdfSopenharmony_ci * 319f08c3bdfSopenharmony_ci * Argument: 320f08c3bdfSopenharmony_ci * str : nano second value in character representation 321f08c3bdfSopenharmony_ci * ts_p : pointer to a timespec structure 322f08c3bdfSopenharmony_ci * 323f08c3bdfSopenharmony_ci * Return value: 324f08c3bdfSopenharmony_ci * 0: Success 325f08c3bdfSopenharmony_ci * 1: Fail 326f08c3bdfSopenharmony_ci */ 327f08c3bdfSopenharmony_ciint strtotimespec(const char *str, struct timespec *ts_p) 328f08c3bdfSopenharmony_ci{ 329f08c3bdfSopenharmony_ci size_t len; 330f08c3bdfSopenharmony_ci char *sec_str; 331f08c3bdfSopenharmony_ci unsigned long sec = 0; 332f08c3bdfSopenharmony_ci unsigned long nsec = 0; 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci len = strlen(str); 335f08c3bdfSopenharmony_ci if (len > 9) { /* Check the specified value is bigger than 999999999 */ 336f08c3bdfSopenharmony_ci sec_str = calloc((len - 9 + 1), sizeof(char)); 337f08c3bdfSopenharmony_ci strncpy(sec_str, str, len - 9); 338f08c3bdfSopenharmony_ci sec = strtoul(sec_str, NULL, 0); 339f08c3bdfSopenharmony_ci if (sec > 0x7fffffff) 340f08c3bdfSopenharmony_ci return 1; 341f08c3bdfSopenharmony_ci free(sec_str); 342f08c3bdfSopenharmony_ci nsec = strtoul(str + len - 9, NULL, 0); 343f08c3bdfSopenharmony_ci } else { 344f08c3bdfSopenharmony_ci nsec = strtoul(str, NULL, 0); 345f08c3bdfSopenharmony_ci } 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci ts_p->tv_sec = sec; 348f08c3bdfSopenharmony_ci ts_p->tv_nsec = nsec; 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci return 0; 351f08c3bdfSopenharmony_ci} 352f08c3bdfSopenharmony_ci 353f08c3bdfSopenharmony_ci/* 354f08c3bdfSopenharmony_ci * Function: get_a_lla_byifindex() 355f08c3bdfSopenharmony_ci * 356f08c3bdfSopenharmony_ci * Description: 357f08c3bdfSopenharmony_ci * This function gets one of the link-local addresses which is specified 358f08c3bdfSopenharmony_ci * by interface index 359f08c3bdfSopenharmony_ci * 360f08c3bdfSopenharmony_ci * Argument: 361f08c3bdfSopenharmony_ci * lla_p : pointer to a sockaddr_in6 structure which stores the lla 362f08c3bdfSopenharmony_ci * ifindex : index of the interface 363f08c3bdfSopenharmony_ci * 364f08c3bdfSopenharmony_ci * Return value: 365f08c3bdfSopenharmony_ci * 0: Success 366f08c3bdfSopenharmony_ci * 1: Fail 367f08c3bdfSopenharmony_ci */ 368f08c3bdfSopenharmony_ciint get_a_lla_byifindex(struct sockaddr_in6 *lla_p, int ifindex) 369f08c3bdfSopenharmony_ci{ 370f08c3bdfSopenharmony_ci FILE *fp; 371f08c3bdfSopenharmony_ci int ret; 372f08c3bdfSopenharmony_ci unsigned int oct[16]; 373f08c3bdfSopenharmony_ci int ifidx, prefixlen, scope; 374f08c3bdfSopenharmony_ci char line[PROC_IFINET6_FILE_LINELENGTH]; 375f08c3bdfSopenharmony_ci int pos; 376f08c3bdfSopenharmony_ci 377f08c3bdfSopenharmony_ci if ((fp = fopen(PROC_IFINET6_FILE, "r")) == NULL) { 378f08c3bdfSopenharmony_ci fprintf(stderr, "Faile to open %s\n", PROC_IFINET6_FILE); 379f08c3bdfSopenharmony_ci return 1; 380f08c3bdfSopenharmony_ci } 381f08c3bdfSopenharmony_ci 382f08c3bdfSopenharmony_ci while (fgets(line, PROC_IFINET6_FILE_LINELENGTH, fp) != NULL) { 383f08c3bdfSopenharmony_ci ret = sscanf(line, 384f08c3bdfSopenharmony_ci "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x %x %x %x", 385f08c3bdfSopenharmony_ci &oct[0], &oct[1], &oct[2], &oct[3], 386f08c3bdfSopenharmony_ci &oct[4], &oct[5], &oct[6], &oct[7], 387f08c3bdfSopenharmony_ci &oct[8], &oct[9], &oct[10], &oct[11], 388f08c3bdfSopenharmony_ci &oct[12], &oct[13], &oct[14], &oct[15], 389f08c3bdfSopenharmony_ci &ifidx, &prefixlen, &scope); 390f08c3bdfSopenharmony_ci 391f08c3bdfSopenharmony_ci if (ret == EOF) 392f08c3bdfSopenharmony_ci fatal_error("scanf()"); 393f08c3bdfSopenharmony_ci else if (ret != 19) 394f08c3bdfSopenharmony_ci fatal_error 395f08c3bdfSopenharmony_ci ("The number of input item is less than the expected"); 396f08c3bdfSopenharmony_ci 397f08c3bdfSopenharmony_ci if (ifidx != ifindex) 398f08c3bdfSopenharmony_ci continue; 399f08c3bdfSopenharmony_ci 400f08c3bdfSopenharmony_ci if (prefixlen != 64) 401f08c3bdfSopenharmony_ci continue; 402f08c3bdfSopenharmony_ci 403f08c3bdfSopenharmony_ci if (scope != PROC_IFINET6_LINKLOCAL) 404f08c3bdfSopenharmony_ci continue; 405f08c3bdfSopenharmony_ci 406f08c3bdfSopenharmony_ci /* Find a link-local address */ 407f08c3bdfSopenharmony_ci lla_p->sin6_family = AF_INET6; 408f08c3bdfSopenharmony_ci lla_p->sin6_port = 0; 409f08c3bdfSopenharmony_ci lla_p->sin6_flowinfo = 0; 410f08c3bdfSopenharmony_ci lla_p->sin6_scope_id = ifindex; 411f08c3bdfSopenharmony_ci 412f08c3bdfSopenharmony_ci for (pos = 0; pos < 16; pos++) 413f08c3bdfSopenharmony_ci lla_p->sin6_addr.s6_addr[pos] = oct[pos]; 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci return 0; 416f08c3bdfSopenharmony_ci } 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci fprintf(stderr, "No link-local address is found.\n"); 419f08c3bdfSopenharmony_ci return 1; 420f08c3bdfSopenharmony_ci} 421f08c3bdfSopenharmony_ci 422f08c3bdfSopenharmony_ci/* 423f08c3bdfSopenharmony_ci * Function: get_maddrinfo() 424f08c3bdfSopenharmony_ci * 425f08c3bdfSopenharmony_ci * Description: 426f08c3bdfSopenharmony_ci * This function translates multicast address informantion into the addrinfo 427f08c3bdfSopenharmony_ci * structure 428f08c3bdfSopenharmony_ci * 429f08c3bdfSopenharmony_ci * Argument: 430f08c3bdfSopenharmony_ci * family: protocol family 431f08c3bdfSopenharmony_ci * maddr: multicast address in character string 432f08c3bdfSopenharmony_ci * portnum: port number in character string 433f08c3bdfSopenharmony_ci * 434f08c3bdfSopenharmony_ci * Return value: 435f08c3bdfSopenharmony_ci * pointer to the addrinfo which stores the multicast address information 436f08c3bdfSopenharmony_ci */ 437f08c3bdfSopenharmony_cistruct addrinfo *get_maddrinfo(sa_family_t family, const char *maddr, 438f08c3bdfSopenharmony_ci const char *portnum) 439f08c3bdfSopenharmony_ci{ 440f08c3bdfSopenharmony_ci struct addrinfo hints; /* hints for getaddrinfo() */ 441f08c3bdfSopenharmony_ci struct addrinfo *res; /* pointer to addrinfo structure */ 442f08c3bdfSopenharmony_ci int err; /* return value of getaddrinfo */ 443f08c3bdfSopenharmony_ci 444f08c3bdfSopenharmony_ci memset(&hints, '\0', sizeof(struct addrinfo)); 445f08c3bdfSopenharmony_ci hints.ai_family = family; 446f08c3bdfSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 447f08c3bdfSopenharmony_ci hints.ai_protocol = IPPROTO_UDP; 448f08c3bdfSopenharmony_ci hints.ai_flags |= AI_NUMERICHOST; 449f08c3bdfSopenharmony_ci 450f08c3bdfSopenharmony_ci err = getaddrinfo(maddr, portnum, &hints, &res); 451f08c3bdfSopenharmony_ci if (err) { 452f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err)); 453f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 454f08c3bdfSopenharmony_ci } 455f08c3bdfSopenharmony_ci if (res->ai_next) { 456f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): multiple address is found."); 457f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 458f08c3bdfSopenharmony_ci } 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci return res; 461f08c3bdfSopenharmony_ci} 462f08c3bdfSopenharmony_ci 463f08c3bdfSopenharmony_ci/* 464f08c3bdfSopenharmony_ci * Function: create_group_info() 465f08c3bdfSopenharmony_ci * 466f08c3bdfSopenharmony_ci * Description: 467f08c3bdfSopenharmony_ci * This function create a group information to join the group 468f08c3bdfSopenharmony_ci * This function calls malloc to store the information 469f08c3bdfSopenharmony_ci * 470f08c3bdfSopenharmony_ci * Argument: 471f08c3bdfSopenharmony_ci * ifindex: interface index 472f08c3bdfSopenharmony_ci * mainfo_p: pointer to addrinfo structure for multicast address 473f08c3bdfSopenharmony_ci * 474f08c3bdfSopenharmony_ci * Return value: 475f08c3bdfSopenharmony_ci * pointer to allocated group_filter structure 476f08c3bdfSopenharmony_ci */ 477f08c3bdfSopenharmony_cistruct group_req *create_group_info(uint32_t ifindex, struct addrinfo *mainfo_p) 478f08c3bdfSopenharmony_ci{ 479f08c3bdfSopenharmony_ci struct group_req *greq; 480f08c3bdfSopenharmony_ci 481f08c3bdfSopenharmony_ci /* allocate memory for group_filter */ 482f08c3bdfSopenharmony_ci greq = (struct group_req *)calloc(1, sizeof(struct group_req)); 483f08c3bdfSopenharmony_ci if (greq == NULL) 484f08c3bdfSopenharmony_ci fatal_error("calloc()"); 485f08c3bdfSopenharmony_ci 486f08c3bdfSopenharmony_ci /* substitute informations */ 487f08c3bdfSopenharmony_ci greq->gr_interface = ifindex; 488f08c3bdfSopenharmony_ci memcpy(&greq->gr_group, mainfo_p->ai_addr, mainfo_p->ai_addrlen); 489f08c3bdfSopenharmony_ci 490f08c3bdfSopenharmony_ci return greq; 491f08c3bdfSopenharmony_ci} 492f08c3bdfSopenharmony_ci 493f08c3bdfSopenharmony_ci/* 494f08c3bdfSopenharmony_ci * Function: create_source_filter() 495f08c3bdfSopenharmony_ci * 496f08c3bdfSopenharmony_ci * Description: 497f08c3bdfSopenharmony_ci * This function create a source filter. 498f08c3bdfSopenharmony_ci * This function calls malloc to store the source filter. 499f08c3bdfSopenharmony_ci * 500f08c3bdfSopenharmony_ci * Argument: 501f08c3bdfSopenharmony_ci * ifindex: interface index 502f08c3bdfSopenharmony_ci * mainfo_p: pointer to addrinfo structure for multicast address 503f08c3bdfSopenharmony_ci * fmode: filter mode 504f08c3bdfSopenharmony_ci * saddrs: comma separated array of the source addresses 505f08c3bdfSopenharmony_ci * 506f08c3bdfSopenharmony_ci * Return value: 507f08c3bdfSopenharmony_ci * pointer to allocated group_filter structure 508f08c3bdfSopenharmony_ci */ 509f08c3bdfSopenharmony_cistruct group_filter *create_source_filter(uint32_t ifindex, 510f08c3bdfSopenharmony_ci struct addrinfo *mainfo_p, 511f08c3bdfSopenharmony_ci uint32_t fmode, char *saddrs) 512f08c3bdfSopenharmony_ci{ 513f08c3bdfSopenharmony_ci struct group_filter *gsf; /* pointer to group_filter structure */ 514f08c3bdfSopenharmony_ci uint32_t numsrc; /* number of source address */ 515f08c3bdfSopenharmony_ci struct addrinfo hints; /* hints for getaddrinfo() */ 516f08c3bdfSopenharmony_ci struct addrinfo *res; /* pointer to addrinfo structure */ 517f08c3bdfSopenharmony_ci int err; /* return value of getaddrinfo */ 518f08c3bdfSopenharmony_ci uint32_t idx; 519f08c3bdfSopenharmony_ci char *sp, *ep; 520f08c3bdfSopenharmony_ci 521f08c3bdfSopenharmony_ci /* calculate the number of source address */ 522f08c3bdfSopenharmony_ci numsrc = 1; 523f08c3bdfSopenharmony_ci for (sp = saddrs; *sp != '\0'; sp++) 524f08c3bdfSopenharmony_ci if (*sp == ',') 525f08c3bdfSopenharmony_ci numsrc++; 526f08c3bdfSopenharmony_ci 527f08c3bdfSopenharmony_ci if (debug) 528f08c3bdfSopenharmony_ci fprintf(stderr, "number of source address is %u\n", numsrc); 529f08c3bdfSopenharmony_ci 530f08c3bdfSopenharmony_ci /* allocate memory for group_filter */ 531f08c3bdfSopenharmony_ci gsf = (struct group_filter *)calloc(1, GROUP_FILTER_SIZE(numsrc)); 532f08c3bdfSopenharmony_ci if (gsf == NULL) 533f08c3bdfSopenharmony_ci fatal_error("calloc()"); 534f08c3bdfSopenharmony_ci 535f08c3bdfSopenharmony_ci /* substitute interface index, multicast address, filter mode */ 536f08c3bdfSopenharmony_ci gsf->gf_interface = ifindex; 537f08c3bdfSopenharmony_ci memcpy(&gsf->gf_group, mainfo_p->ai_addr, mainfo_p->ai_addrlen); 538f08c3bdfSopenharmony_ci gsf->gf_fmode = fmode; 539f08c3bdfSopenharmony_ci gsf->gf_numsrc = numsrc; 540f08c3bdfSopenharmony_ci 541f08c3bdfSopenharmony_ci /* extract source address aray and substitute the addersses */ 542f08c3bdfSopenharmony_ci memset(&hints, '\0', sizeof(struct addrinfo)); 543f08c3bdfSopenharmony_ci hints.ai_family = mainfo_p->ai_family; 544f08c3bdfSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 545f08c3bdfSopenharmony_ci hints.ai_protocol = IPPROTO_UDP; 546f08c3bdfSopenharmony_ci hints.ai_flags |= AI_NUMERICHOST; 547f08c3bdfSopenharmony_ci 548f08c3bdfSopenharmony_ci /* extract source address aray and substitute the addersses */ 549f08c3bdfSopenharmony_ci memset(&hints, '\0', sizeof(struct addrinfo)); 550f08c3bdfSopenharmony_ci hints.ai_family = mainfo_p->ai_family; 551f08c3bdfSopenharmony_ci hints.ai_socktype = SOCK_DGRAM; 552f08c3bdfSopenharmony_ci hints.ai_protocol = IPPROTO_UDP; 553f08c3bdfSopenharmony_ci hints.ai_flags |= AI_NUMERICHOST; 554f08c3bdfSopenharmony_ci 555f08c3bdfSopenharmony_ci sp = saddrs; 556f08c3bdfSopenharmony_ci for (idx = 0; idx < numsrc; idx++) { 557f08c3bdfSopenharmony_ci ep = strchr(sp, ','); 558f08c3bdfSopenharmony_ci if (ep != NULL) 559f08c3bdfSopenharmony_ci *ep = '\0'; 560f08c3bdfSopenharmony_ci if (debug) 561f08c3bdfSopenharmony_ci fprintf(stderr, "source address[%u]: %s\n", idx, sp); 562f08c3bdfSopenharmony_ci 563f08c3bdfSopenharmony_ci err = getaddrinfo(sp, NULL, &hints, &res); 564f08c3bdfSopenharmony_ci if (err) { 565f08c3bdfSopenharmony_ci fprintf(stderr, "getaddrinfo(): %s\n", 566f08c3bdfSopenharmony_ci gai_strerror(err)); 567f08c3bdfSopenharmony_ci exit(EXIT_FAILURE); 568f08c3bdfSopenharmony_ci } 569f08c3bdfSopenharmony_ci 570f08c3bdfSopenharmony_ci memcpy(&gsf->gf_slist[idx], res->ai_addr, res->ai_addrlen); 571f08c3bdfSopenharmony_ci freeaddrinfo(res); 572f08c3bdfSopenharmony_ci sp = ep + 1; 573f08c3bdfSopenharmony_ci } 574f08c3bdfSopenharmony_ci 575f08c3bdfSopenharmony_ci return gsf; 576f08c3bdfSopenharmony_ci} 577