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