1cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/******************************************************************************/ 2cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* */ 38af2363347544d3721689a38e5d4823d35952fd2mreed/* Copyright (c) International Business Machines Corp., 2005, 2006 */ 4cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* */ 5cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* This program is free software; you can redistribute it and/or modify */ 6cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* it under the terms of the GNU General Public License as published by */ 7cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* the Free Software Foundation; either version 2 of the License, or */ 8cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* (at your option) any later version. */ 9cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* */ 10cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* This program is distributed in the hope that it will be useful, */ 11cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ 12cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */ 13cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* the GNU General Public License for more details. */ 14cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* */ 15cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* You should have received a copy of the GNU General Public License */ 16cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 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 */ 18cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* */ 19cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/******************************************************************************/ 20cd30c339dae692a3eb5c5fc55f70726457f4756bmridge 21cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 22cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * File: 238af2363347544d3721689a38e5d4823d35952fd2mreed * ns-common.c 24cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 25cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Description: 268af2363347544d3721689a38e5d4823d35952fd2mreed * Common functions and variables in the ns-tools 27cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 28cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Author: 29cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Mitsuru Chinen <mitch@jp.ibm.com> 30cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 31cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * History: 32cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Oct 19 2005 - Created (Mitsuru Chinen) 338af2363347544d3721689a38e5d4823d35952fd2mreed * May 1 2006 - Added functions for broken_ip, route, multicast tests 34cd30c339dae692a3eb5c5fc55f70726457f4756bmridge *---------------------------------------------------------------------------*/ 35cd30c339dae692a3eb5c5fc55f70726457f4756bmridge 36cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 37cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Fixed values 38cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */ 39cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#define PROC_RMEM_MAX "/proc/sys/net/core/rmem_max" 40cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#define PROC_WMEM_MAX "/proc/sys/net/core/wmem_max" 41cd30c339dae692a3eb5c5fc55f70726457f4756bmridge 42cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 43cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Standard Header Files 44cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */ 45cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <stdio.h> 46cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <stdlib.h> 478af2363347544d3721689a38e5d4823d35952fd2mreed#include <string.h> 488af2363347544d3721689a38e5d4823d35952fd2mreed#include <sys/ioctl.h> 49cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/types.h> 50cd30c339dae692a3eb5c5fc55f70726457f4756bmridge#include <sys/socket.h> 518af2363347544d3721689a38e5d4823d35952fd2mreed#include <net/ethernet.h> 528af2363347544d3721689a38e5d4823d35952fd2mreed#include <net/if.h> 538af2363347544d3721689a38e5d4823d35952fd2mreed#include <net/if_arp.h> 548af2363347544d3721689a38e5d4823d35952fd2mreed 558af2363347544d3721689a38e5d4823d35952fd2mreed#include "ns-mcast.h" 568af2363347544d3721689a38e5d4823d35952fd2mreed#define NS_COMMON 1 578af2363347544d3721689a38e5d4823d35952fd2mreed#include "ns-traffic.h" 58cd30c339dae692a3eb5c5fc55f70726457f4756bmridge 59cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 60cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Function: fatal_error() 61cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 62cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Description: 63cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Output an error message then exit the program with EXIT_FAILURE 64cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 65cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Argument: 66cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * errmsg: message printed by perror() 67cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 68cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Return value: 69cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * This function does not return. 70cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */ 71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid fatal_error(char *errmsg) 72cd30c339dae692a3eb5c5fc55f70726457f4756bmridge{ 73354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao perror(errmsg); 74354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 75cd30c339dae692a3eb5c5fc55f70726457f4756bmridge} 76cd30c339dae692a3eb5c5fc55f70726457f4756bmridge 77cd30c339dae692a3eb5c5fc55f70726457f4756bmridge/* 78cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Function: maximize_sockbuf() 798af2363347544d3721689a38e5d4823d35952fd2mreed * 80cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Descripton: 81cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * This function maximize the send and receive buffer size of a socket 82cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 83cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Argument: 84cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * sd: target socket descriptor 85cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * 86cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * Return value: 87cd30c339dae692a3eb5c5fc55f70726457f4756bmridge * None 88cd30c339dae692a3eb5c5fc55f70726457f4756bmridge */ 89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid maximize_sockbuf(int sd) 90cd30c339dae692a3eb5c5fc55f70726457f4756bmridge{ 91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t idx; 92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int level[] = { SO_RCVBUF, SO_SNDBUF }; 93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *procfile[] = { PROC_RMEM_MAX, PROC_WMEM_MAX }; 94354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *bufname[] = { "rcvbuf", "sndbuf" }; 95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (idx = 0; idx < (sizeof(level) / sizeof(int)); idx++) { 97354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FILE *fp; /* File pointer to a proc file */ 98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int bufsiz; /* buffer size of socket */ 99354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned int optlen; /* size of sd option parameter */ 100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((fp = fopen(procfile[idx], "r")) == NULL) { 102354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Failed to open %s\n", procfile[idx]); 103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("fopen()"); 104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((fscanf(fp, "%d", &bufsiz)) != 1) { 106354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Failed to read from %s\n", 107354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao procfile[idx]); 108354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("fscanf()"); 109354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 110354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (setsockopt 111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (sd, SOL_SOCKET, level[idx], &bufsiz, sizeof(int))) { 112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("setsockopt()"); 113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (fclose(fp)) { 115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Failed to close to %s\n", 116354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao procfile[idx]); 117354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("fopen()"); 118354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) { 121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao optlen = sizeof(bufsiz); 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (getsockopt 123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao (sd, SOL_SOCKET, level[idx], &bufsiz, 124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &optlen) < 0) { 125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("getsockopt()"); 126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "socket %s size is %d\n", bufname[idx], 128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao bufsiz); 129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 130cd30c339dae692a3eb5c5fc55f70726457f4756bmridge } 131cd30c339dae692a3eb5c5fc55f70726457f4756bmridge} 1328af2363347544d3721689a38e5d4823d35952fd2mreed 1338af2363347544d3721689a38e5d4823d35952fd2mreed/* 1348af2363347544d3721689a38e5d4823d35952fd2mreed * Function: calc_checksum() 1358af2363347544d3721689a38e5d4823d35952fd2mreed * 1368af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 1378af2363347544d3721689a38e5d4823d35952fd2mreed * This function calculate the checksum of IPv4 or ICMP 1388af2363347544d3721689a38e5d4823d35952fd2mreed * 1398af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 1408af2363347544d3721689a38e5d4823d35952fd2mreed * data: pointer to target data for checksum 1418af2363347544d3721689a38e5d4823d35952fd2mreed * size: target data size 1428af2363347544d3721689a38e5d4823d35952fd2mreed * 1438af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 1448af2363347544d3721689a38e5d4823d35952fd2mreed * None 1458af2363347544d3721689a38e5d4823d35952fd2mreed */ 146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaou_int16_t calc_checksum(u_int16_t * data, size_t size) 1478af2363347544d3721689a38e5d4823d35952fd2mreed{ 148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao u_int32_t sum; 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao u_int16_t *pos; 150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t rest; 1518af2363347544d3721689a38e5d4823d35952fd2mreed 152354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum = 0; 153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao pos = data; 154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (rest = size; rest > 1; rest -= 2) 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum += *(pos++); 1568af2363347544d3721689a38e5d4823d35952fd2mreed 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (rest > 0) 158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum += (*pos) & 0xff00; 1598af2363347544d3721689a38e5d4823d35952fd2mreed 160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum = (sum & 0xffff) + (sum >> 16); 161354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum = (sum & 0xffff) + (sum >> 16); 162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sum = ~sum; 1638af2363347544d3721689a38e5d4823d35952fd2mreed 164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return sum; 1658af2363347544d3721689a38e5d4823d35952fd2mreed} 1668af2363347544d3721689a38e5d4823d35952fd2mreed 1678af2363347544d3721689a38e5d4823d35952fd2mreed/* 1688af2363347544d3721689a38e5d4823d35952fd2mreed * Function: fill_payload() 1698af2363347544d3721689a38e5d4823d35952fd2mreed * 1708af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 1718af2363347544d3721689a38e5d4823d35952fd2mreed * This function fills the payload 1728af2363347544d3721689a38e5d4823d35952fd2mreed * 1738af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 1748af2363347544d3721689a38e5d4823d35952fd2mreed * payload_p: pointer to data of payload 1758af2363347544d3721689a38e5d4823d35952fd2mreed * size: payload size 1768af2363347544d3721689a38e5d4823d35952fd2mreed * 1778af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 1788af2363347544d3721689a38e5d4823d35952fd2mreed * None 1798af2363347544d3721689a38e5d4823d35952fd2mreed */ 180354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid fill_payload(unsigned char *payload_p, size_t size) 1818af2363347544d3721689a38e5d4823d35952fd2mreed{ 182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t idx; 1838af2363347544d3721689a38e5d4823d35952fd2mreed 184354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (idx = 0; idx < size; idx++) 185354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao *(payload_p + idx) = idx % 0x100; 1868af2363347544d3721689a38e5d4823d35952fd2mreed} 1878af2363347544d3721689a38e5d4823d35952fd2mreed 1888af2363347544d3721689a38e5d4823d35952fd2mreed/* 1898af2363347544d3721689a38e5d4823d35952fd2mreed * Function: rand_within() 1908af2363347544d3721689a38e5d4823d35952fd2mreed * 1918af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 1928af2363347544d3721689a38e5d4823d35952fd2mreed * This function returns a presudo-random integer within specified range 1938af2363347544d3721689a38e5d4823d35952fd2mreed * 1948af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 1958af2363347544d3721689a38e5d4823d35952fd2mreed * first: Fisrt value of the range. If negative, assumed 0 1968af2363347544d3721689a38e5d4823d35952fd2mreed * last : Last value of the range. If bigger than RAND_MAX, assumed RAND_MAX 1978af2363347544d3721689a38e5d4823d35952fd2mreed * 1988af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 1998af2363347544d3721689a38e5d4823d35952fd2mreed * integer value between first to last 2008af2363347544d3721689a38e5d4823d35952fd2mreed */ 201354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint rand_within(int first, int last) 2028af2363347544d3721689a38e5d4823d35952fd2mreed{ 203354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned int num; 204354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int rand_val; 2058af2363347544d3721689a38e5d4823d35952fd2mreed 206354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao first = first < 0 ? 0 : first; 207354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao last = RAND_MAX < (unsigned int)last ? RAND_MAX : last; 2088af2363347544d3721689a38e5d4823d35952fd2mreed 209354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao num = last - first + 1U; 210354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rand_val = rand() / ((RAND_MAX + 1U) / num) + first; 2118af2363347544d3721689a38e5d4823d35952fd2mreed 212354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return rand_val; 2138af2363347544d3721689a38e5d4823d35952fd2mreed} 2148af2363347544d3721689a38e5d4823d35952fd2mreed 2158af2363347544d3721689a38e5d4823d35952fd2mreed/* 2168af2363347544d3721689a38e5d4823d35952fd2mreed * Function: bit_change_seed 2178af2363347544d3721689a38e5d4823d35952fd2mreed * 2188af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 2198af2363347544d3721689a38e5d4823d35952fd2mreed * This function creates a seed to change 1 bit at random position 2208af2363347544d3721689a38e5d4823d35952fd2mreed * 2218af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 2228af2363347544d3721689a38e5d4823d35952fd2mreed * bitsize : bit size of data whose bit would be changed 2238af2363347544d3721689a38e5d4823d35952fd2mreed * oversize: This value controls whether a bit is changed or not 2248af2363347544d3721689a38e5d4823d35952fd2mreed * 2258af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 2268af2363347544d3721689a38e5d4823d35952fd2mreed * seed of the bit for change. 2278af2363347544d3721689a38e5d4823d35952fd2mreed */ 228354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaou_int32_t bit_change_seed(size_t bitsize, size_t oversize) 2298af2363347544d3721689a38e5d4823d35952fd2mreed{ 230354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int rand_val; 231354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao u_int32_t seed; 232354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao rand_val = rand() / ((RAND_MAX + 1U) / (bitsize + oversize)); 2338af2363347544d3721689a38e5d4823d35952fd2mreed 234354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao seed = (rand_val < bitsize) ? (0x00000001 << rand_val) : 0; 2358af2363347544d3721689a38e5d4823d35952fd2mreed 236354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 237354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Bit seed is %08x\n", seed); 2388af2363347544d3721689a38e5d4823d35952fd2mreed 239354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return seed; 2408af2363347544d3721689a38e5d4823d35952fd2mreed} 2418af2363347544d3721689a38e5d4823d35952fd2mreed 2428af2363347544d3721689a38e5d4823d35952fd2mreed/* 2438af2363347544d3721689a38e5d4823d35952fd2mreed * Function: eth_pton() 2448af2363347544d3721689a38e5d4823d35952fd2mreed * 2458af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 2468af2363347544d3721689a38e5d4823d35952fd2mreed * This function convert a string to struct sockaddr_ll (Ethernet) 2478af2363347544d3721689a38e5d4823d35952fd2mreed * Note) The ifindex is set to `any'. 2488af2363347544d3721689a38e5d4823d35952fd2mreed * 2498af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 2508af2363347544d3721689a38e5d4823d35952fd2mreed * af : AF_INET or AF_INET6 2518af2363347544d3721689a38e5d4823d35952fd2mreed * str: Pointer to a string which represents MAC address 2528af2363347544d3721689a38e5d4823d35952fd2mreed * ll : pointer to struct sockaddr_ll 2538af2363347544d3721689a38e5d4823d35952fd2mreed * 2548af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 2558af2363347544d3721689a38e5d4823d35952fd2mreed * 0 : Success 2568af2363347544d3721689a38e5d4823d35952fd2mreed * 1 : Fail 2578af2363347544d3721689a38e5d4823d35952fd2mreed */ 258354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint eth_pton(int af, const char *str, struct sockaddr_ll *ll) 2598af2363347544d3721689a38e5d4823d35952fd2mreed{ 260354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t idx; 261354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned char *addr_p; 262354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned int val[ETH_ALEN]; 263354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 264354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_family = AF_PACKET; /* Always AF_PACKET */ 265354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (af == AF_INET) 266354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_protocol = htons(ETH_P_IP); /* IPv4 */ 267354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao else 268354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_protocol = htons(ETH_P_IPV6); /* IPv6 */ 269354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_ifindex = 0; /* any interface */ 270354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_hatype = ARPHRD_ETHER; /* Header type */ 271354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_pkttype = PACKET_OTHERHOST; /* Packet type */ 272354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ll->sll_halen = ETH_ALEN; /* Length of address */ 273354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 274354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Physical layer address */ 275354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sscanf(str, "%2x:%2x:%2x:%2x:%2x:%2x", &val[0], &val[1], 276354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &val[2], &val[3], &val[4], &val[5]) != ETH_ALEN) { 277354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "%s is not a valid MAC address", str); 278354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 1; 279354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 2808af2363347544d3721689a38e5d4823d35952fd2mreed 281354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao addr_p = (unsigned char *)ll->sll_addr; 282354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (idx = 0; idx < ETH_ALEN; idx++) 283354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao addr_p[idx] = val[idx]; 2848af2363347544d3721689a38e5d4823d35952fd2mreed 285354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 0; 2868af2363347544d3721689a38e5d4823d35952fd2mreed} 2878af2363347544d3721689a38e5d4823d35952fd2mreed 2888af2363347544d3721689a38e5d4823d35952fd2mreed/* 2898af2363347544d3721689a38e5d4823d35952fd2mreed * Function: get_ifinfo() 2908af2363347544d3721689a38e5d4823d35952fd2mreed * 2918af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 2928af2363347544d3721689a38e5d4823d35952fd2mreed * This function gets the interface information with ioctl() 2938af2363347544d3721689a38e5d4823d35952fd2mreed * 2948af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 2958af2363347544d3721689a38e5d4823d35952fd2mreed * ans : ifreq structure to store the information 2968af2363347544d3721689a38e5d4823d35952fd2mreed * sock_fd : socket file descriptor 2978af2363347544d3721689a38e5d4823d35952fd2mreed * ifname : interface name 2988af2363347544d3721689a38e5d4823d35952fd2mreed * query : ioctl request value 2998af2363347544d3721689a38e5d4823d35952fd2mreed * 3008af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 3018af2363347544d3721689a38e5d4823d35952fd2mreed * None 3028af2363347544d3721689a38e5d4823d35952fd2mreed * 3038af2363347544d3721689a38e5d4823d35952fd2mreed */ 304354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaovoid get_ifinfo(struct ifreq *ans, int sock_fd, const char *ifname, int query) 3058af2363347544d3721689a38e5d4823d35952fd2mreed{ 306354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(ans, '\0', sizeof(struct ifreq)); 307354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strncpy(ans->ifr_name, ifname, (IFNAMSIZ - 1)); 3088af2363347544d3721689a38e5d4823d35952fd2mreed 309354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ioctl(sock_fd, query, ans) < 0) 310354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("ioctl()"); 3118af2363347544d3721689a38e5d4823d35952fd2mreed} 3128af2363347544d3721689a38e5d4823d35952fd2mreed 3138af2363347544d3721689a38e5d4823d35952fd2mreed/* 3148af2363347544d3721689a38e5d4823d35952fd2mreed * Function: strtotimespec() 3158af2363347544d3721689a38e5d4823d35952fd2mreed * 3168af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 3178af2363347544d3721689a38e5d4823d35952fd2mreed * This function converts a string to timespec structure 3188af2363347544d3721689a38e5d4823d35952fd2mreed * 3198af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 3208af2363347544d3721689a38e5d4823d35952fd2mreed * str : nano second value in character representation 3218af2363347544d3721689a38e5d4823d35952fd2mreed * ts_p : pointer to a timespec structure 3228af2363347544d3721689a38e5d4823d35952fd2mreed * 3238af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 3248af2363347544d3721689a38e5d4823d35952fd2mreed * 0: Success 3258af2363347544d3721689a38e5d4823d35952fd2mreed * 1: Fail 3268af2363347544d3721689a38e5d4823d35952fd2mreed */ 327354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint strtotimespec(const char *str, struct timespec *ts_p) 3288af2363347544d3721689a38e5d4823d35952fd2mreed{ 329354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao size_t len; 330354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *sec_str; 331354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned long sec = 0; 332354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned long nsec = 0; 333354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 334354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao len = strlen(str); 335354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (len > 9) { /* Check the specified value is bigger than 999999999 */ 336354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sec_str = calloc((len - 9 + 1), sizeof(char)); 337354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strncpy(sec_str, str, len - 9); 338354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sec = strtoul(sec_str, NULL, 0); 339354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sec > 0x7fffffff) 340354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 1; 341354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao free(sec_str); 342354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao nsec = strtoul(str + len - 9, NULL, 0); 343354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 344354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao nsec = strtoul(str, NULL, 0); 345354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 346354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 347354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ts_p->tv_sec = sec; 348354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ts_p->tv_nsec = nsec; 349354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 350354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 0; 3518af2363347544d3721689a38e5d4823d35952fd2mreed} 3528af2363347544d3721689a38e5d4823d35952fd2mreed 3538af2363347544d3721689a38e5d4823d35952fd2mreed/* 3548af2363347544d3721689a38e5d4823d35952fd2mreed * Function: get_a_lla_byifindex() 3558af2363347544d3721689a38e5d4823d35952fd2mreed * 3568af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 3578af2363347544d3721689a38e5d4823d35952fd2mreed * This function gets one of the link-local addresses which is specified 3588af2363347544d3721689a38e5d4823d35952fd2mreed * by interface index 3598af2363347544d3721689a38e5d4823d35952fd2mreed * 3608af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 3618af2363347544d3721689a38e5d4823d35952fd2mreed * lla_p : pointer to a sockaddr_in6 sturcture which stores the lla 3628af2363347544d3721689a38e5d4823d35952fd2mreed * ifindex : index of the interface 3638af2363347544d3721689a38e5d4823d35952fd2mreed * 3648af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 3658af2363347544d3721689a38e5d4823d35952fd2mreed * 0: Success 3668af2363347544d3721689a38e5d4823d35952fd2mreed * 1: Fail 3678af2363347544d3721689a38e5d4823d35952fd2mreed */ 368354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaoint get_a_lla_byifindex(struct sockaddr_in6 *lla_p, int ifindex) 3698af2363347544d3721689a38e5d4823d35952fd2mreed{ 370354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FILE *fp; 371354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int ret; 372354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned int oct[16]; 373354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int ifidx, prefixlen, scope; 374354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char line[PROC_IFINET6_FILE_LINELENGTH]; 375354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int pos; 376354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 377354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((fp = fopen(PROC_IFINET6_FILE, "r")) == NULL) { 378354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "Faile to open %s\n", PROC_IFINET6_FILE); 379354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 1; 380354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 3818af2363347544d3721689a38e5d4823d35952fd2mreed 382354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (fgets(line, PROC_IFINET6_FILE_LINELENGTH, fp) != NULL) { 383354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ret = sscanf(line, 384354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x %x %x %x", 385354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &oct[0], &oct[1], &oct[2], &oct[3], 386354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &oct[4], &oct[5], &oct[6], &oct[7], 387354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &oct[8], &oct[9], &oct[10], &oct[11], 388354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &oct[12], &oct[13], &oct[14], &oct[15], 389354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &ifidx, &prefixlen, &scope); 3908af2363347544d3721689a38e5d4823d35952fd2mreed 391354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ret == EOF) 392354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("scanf()"); 393354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao else if (ret != 19) 394354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error 395354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ("The number of input item is less than the expected"); 3968af2363347544d3721689a38e5d4823d35952fd2mreed 397354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ifidx != ifindex) 398354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao continue; 3998af2363347544d3721689a38e5d4823d35952fd2mreed 400354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (prefixlen != 64) 401354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao continue; 4028af2363347544d3721689a38e5d4823d35952fd2mreed 403354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (scope != PROC_IFINET6_LINKLOCAL) 404354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao continue; 4058af2363347544d3721689a38e5d4823d35952fd2mreed 406354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* Find a link-local address */ 407354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lla_p->sin6_family = AF_INET6; 408354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lla_p->sin6_port = 0; 409354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lla_p->sin6_flowinfo = 0; 410354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lla_p->sin6_scope_id = ifindex; 4118af2363347544d3721689a38e5d4823d35952fd2mreed 412354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (pos = 0; pos < 16; pos++) 413354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lla_p->sin6_addr.s6_addr[pos] = oct[pos]; 4148af2363347544d3721689a38e5d4823d35952fd2mreed 415354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 0; 416354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 4178af2363347544d3721689a38e5d4823d35952fd2mreed 418354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "No link-local address is found.\n"); 419354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return 1; 4208af2363347544d3721689a38e5d4823d35952fd2mreed} 4218af2363347544d3721689a38e5d4823d35952fd2mreed 4228af2363347544d3721689a38e5d4823d35952fd2mreed/* 4238af2363347544d3721689a38e5d4823d35952fd2mreed * Function: get_maddrinfo() 4248af2363347544d3721689a38e5d4823d35952fd2mreed * 4258af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 4268af2363347544d3721689a38e5d4823d35952fd2mreed * This function translates multicast address informantion into the addrinfo 4278af2363347544d3721689a38e5d4823d35952fd2mreed * structure 4288af2363347544d3721689a38e5d4823d35952fd2mreed * 4298af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 4308af2363347544d3721689a38e5d4823d35952fd2mreed * family: protocol family 4318af2363347544d3721689a38e5d4823d35952fd2mreed * maddr: multicast address in character string 4328af2363347544d3721689a38e5d4823d35952fd2mreed * portnum: port number in character string 4338af2363347544d3721689a38e5d4823d35952fd2mreed * 4348af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 4358af2363347544d3721689a38e5d4823d35952fd2mreed * pointer to the addrinfo which stores the multicast address information 4368af2363347544d3721689a38e5d4823d35952fd2mreed */ 437354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostruct addrinfo *get_maddrinfo(sa_family_t family, const char *maddr, 438354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao const char *portnum) 4398af2363347544d3721689a38e5d4823d35952fd2mreed{ 440354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct addrinfo hints; /* hints for getaddrinfo() */ 441354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct addrinfo *res; /* pointer to addrinfo structure */ 442354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int err; /* return value of getaddrinfo */ 4438af2363347544d3721689a38e5d4823d35952fd2mreed 444354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&hints, '\0', sizeof(struct addrinfo)); 445354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_family = family; 446354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_socktype = SOCK_DGRAM; 447354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_protocol = IPPROTO_UDP; 448354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_flags |= AI_NUMERICHOST; 449354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 450354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao err = getaddrinfo(maddr, portnum, &hints, &res); 451354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (err) { 452354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(err)); 453354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 454354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 455354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (res->ai_next) { 456354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "getaddrinfo(): multiple address is found."); 457354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 458354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 459354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 460354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return res; 4618af2363347544d3721689a38e5d4823d35952fd2mreed} 4628af2363347544d3721689a38e5d4823d35952fd2mreed 4638af2363347544d3721689a38e5d4823d35952fd2mreed/* 4648af2363347544d3721689a38e5d4823d35952fd2mreed * Function: create_group_info() 4658af2363347544d3721689a38e5d4823d35952fd2mreed * 4668af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 4678af2363347544d3721689a38e5d4823d35952fd2mreed * This function create a group information to join the group 4688af2363347544d3721689a38e5d4823d35952fd2mreed * This function calls malloc to store the information 4698af2363347544d3721689a38e5d4823d35952fd2mreed * 4708af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 4718af2363347544d3721689a38e5d4823d35952fd2mreed * ifindex: interface index 4728af2363347544d3721689a38e5d4823d35952fd2mreed * mainfo_p: pointer to addrinfo structure for multicast address 4738af2363347544d3721689a38e5d4823d35952fd2mreed * 4748af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 4758af2363347544d3721689a38e5d4823d35952fd2mreed * pointer to allocated group_filter structure 4768af2363347544d3721689a38e5d4823d35952fd2mreed */ 477354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostruct group_req *create_group_info(uint32_t ifindex, struct addrinfo *mainfo_p) 4788af2363347544d3721689a38e5d4823d35952fd2mreed{ 479354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct group_req *greq; 4808af2363347544d3721689a38e5d4823d35952fd2mreed 481354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* allocate memory for group_filter */ 482354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao greq = (struct group_req *)calloc(1, sizeof(struct group_req)); 483354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (greq == NULL) 484354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("calloc()"); 4858af2363347544d3721689a38e5d4823d35952fd2mreed 486354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* substitute informations */ 487354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao greq->gr_interface = ifindex; 488354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(&greq->gr_group, mainfo_p->ai_addr, mainfo_p->ai_addrlen); 4898af2363347544d3721689a38e5d4823d35952fd2mreed 490354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return greq; 4918af2363347544d3721689a38e5d4823d35952fd2mreed} 4928af2363347544d3721689a38e5d4823d35952fd2mreed 4938af2363347544d3721689a38e5d4823d35952fd2mreed/* 4948af2363347544d3721689a38e5d4823d35952fd2mreed * Function: create_source_filter() 4958af2363347544d3721689a38e5d4823d35952fd2mreed * 4968af2363347544d3721689a38e5d4823d35952fd2mreed * Description: 4978af2363347544d3721689a38e5d4823d35952fd2mreed * This function create a source filter. 4988af2363347544d3721689a38e5d4823d35952fd2mreed * This function calls malloc to store the source filter. 4998af2363347544d3721689a38e5d4823d35952fd2mreed * 5008af2363347544d3721689a38e5d4823d35952fd2mreed * Argument: 5018af2363347544d3721689a38e5d4823d35952fd2mreed * ifindex: interface index 5028af2363347544d3721689a38e5d4823d35952fd2mreed * mainfo_p: pointer to addrinfo structure for multicast address 5038af2363347544d3721689a38e5d4823d35952fd2mreed * fmode: filter mode 5048af2363347544d3721689a38e5d4823d35952fd2mreed * saddrs: comma separated array of the source addresses 5058af2363347544d3721689a38e5d4823d35952fd2mreed * 5068af2363347544d3721689a38e5d4823d35952fd2mreed * Return value: 5078af2363347544d3721689a38e5d4823d35952fd2mreed * pointer to allocated group_filter structure 5088af2363347544d3721689a38e5d4823d35952fd2mreed */ 509354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gaostruct group_filter *create_source_filter(uint32_t ifindex, 510354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct addrinfo *mainfo_p, 511354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint32_t fmode, char *saddrs) 5128af2363347544d3721689a38e5d4823d35952fd2mreed{ 513354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct group_filter *gsf; /* pointer to group_filter structure */ 514354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint32_t numsrc; /* number of source address */ 515354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct addrinfo hints; /* hints for getaddrinfo() */ 516354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct addrinfo *res; /* pointer to addrinfo structure */ 517354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int err; /* return value of getaddrinfo */ 518354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao uint32_t idx; 519354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *sp, *ep; 520354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 521354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* calculate the number of source address */ 522354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao numsrc = 1; 523354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (sp = saddrs; *sp != '\0'; sp++) 524354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (*sp == ',') 525354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao numsrc++; 5268af2363347544d3721689a38e5d4823d35952fd2mreed 527354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 528354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "number of source address is %u\n", numsrc); 529354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 530354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* allocate memory for group_filter */ 531354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao gsf = (struct group_filter *)calloc(1, GROUP_FILTER_SIZE(numsrc)); 532354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (gsf == NULL) 533354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fatal_error("calloc()"); 534354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 535354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* substitute interface index, multicast address, filter mode */ 536354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao gsf->gf_interface = ifindex; 537354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(&gsf->gf_group, mainfo_p->ai_addr, mainfo_p->ai_addrlen); 538354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao gsf->gf_fmode = fmode; 539354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao gsf->gf_numsrc = numsrc; 540354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 541354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* extract source address aray and substitute the addersses */ 542354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&hints, '\0', sizeof(struct addrinfo)); 543354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_family = mainfo_p->ai_family; 544354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_socktype = SOCK_DGRAM; 545354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_protocol = IPPROTO_UDP; 546354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_flags |= AI_NUMERICHOST; 547354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 548354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* extract source address aray and substitute the addersses */ 549354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memset(&hints, '\0', sizeof(struct addrinfo)); 550354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_family = mainfo_p->ai_family; 551354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_socktype = SOCK_DGRAM; 552354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_protocol = IPPROTO_UDP; 553354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao hints.ai_flags |= AI_NUMERICHOST; 554354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 555354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sp = saddrs; 556354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao for (idx = 0; idx < numsrc; idx++) { 557354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao ep = strchr(sp, ','); 558354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (ep != NULL) 559354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao *ep = '\0'; 560354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (debug) 561354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "source address[%u]: %s\n", idx, sp); 562354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 563354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao err = getaddrinfo(sp, NULL, &hints, &res); 564354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (err) { 565354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "getaddrinfo(): %s\n", 566354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao gai_strerror(err)); 567354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(EXIT_FAILURE); 568354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 569354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 570354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(&gsf->gf_slist[idx], res->ai_addr, res->ai_addrlen); 571354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao freeaddrinfo(res); 572354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sp = ep + 1; 5738af2363347544d3721689a38e5d4823d35952fd2mreed } 5748af2363347544d3721689a38e5d4823d35952fd2mreed 575354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao return gsf; 576ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 577