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