<commit_before>/* Join multicast group(s) and display receive progress
 *
 * Copyright (C) 2004       <NAME> <dlstevens()us!ibm!com>
 * Copyright (C) 2008-2020  <NAME> <troglobit()gmail!com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "config.h"

#include <errno.h>
#include <poll.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "mcjoin.h"

int num_joins = 0;

static int alloc_socket(inet_addr_t group)
{
	inet_addr_t ina = { 0 };
	int sd, val, proto;

	ina.ss_family = group.ss_family;
	inet_addr_set_port(&ina, inet_addr_get_port(&group));

#ifdef AF_INET6
	if (group.ss_family == AF_INET6)
		proto = IPPROTO_IPV6;
	else
#endif
		proto = IPPROTO_IP;

	sd = socket(group.ss_family, SOCK_DGRAM, IPPROTO_UDP);
	if (sd < 0) {
		ERROR("Failed opening socket(): %s", strerror(errno));
		return -1;
	}

	val = 1;
#ifdef SO_REUSEPORT
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)))
		ERROR("Failed enabling SO_REUSEPORT: %s", strerror(errno));
#endif
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)))
		ERROR("Failed enabling SO_REUSEADDR: %s", strerror(errno));

#ifdef AF_INET6
	if (proto == IPPROTO_IPV6) {
		if (setsockopt(sd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)))
			ERROR("Failed enabling IPV6_RECVPKTINFO: %s", strerror(errno));
#ifdef IPV6_MULTICAST_ALL
		val = 0;
		if (setsockopt(sd, proto, IPV6_MULTICAST_ALL, &val, sizeof(val)))
			ERROR("Failed disabling IP_MULTICAST_ALL: %s", strerror(errno));
#endif
	}
#endif
	else {
		val = 1;
#if defined(IP_PKTINFO) || !defined(IP_RECVDSTADDR)
		if (setsockopt(sd, SOL_IP, IP_PKTINFO, &val, sizeof(val)))
			ERROR("Failed enabling IP_PKTINFO: %s", strerror(errno));
#elif defined(IP_RECVDSTADDR)
		if (setsockopt(sd, proto, IP_RECVDSTADDR, &val, sizeof(val)))
			ERROR("Failed enabling IP_RECVDSTADDR: %s", strerror(errno));
#endif
#ifdef IP_MULTICAST_ALL
		val = 0;
		if (setsockopt(sd, proto, IP_MULTICAST_ALL, &val, sizeof(val)))
			ERROR("Failed disabling IP_MULTICAST_ALL: %s", strerror(errno));
#endif
	}

	if (bind(sd, (struct sockaddr *)&ina, inet_addrlen(&ina))) {
		ERROR("Failed binding to socket: %s", strerror(errno));
		close(sd);
		return -1;
	}

	return sd;
}

static int join_group(struct gr *sg)
{
	struct group_source_req gsr;
	struct group_req gr;
	char src[INET_ADDRSTR_LEN] = "*";
	char grp[INET_ADDRSTR_LEN];
	size_t len;
	void *arg;
	int ifindex;
	int sd, op, proto;

	/* Index port with id if IP_MULTICAST_ALL fails */
	sd = alloc_socket(sg->grp);
	if (sd < 0)
		return 1;

	ifindex = if_nametoindex(iface);
	if (!ifindex) {
		ERROR("invalid interface: %s", iface);
		goto error;
	}
	DEBUG("Added iface %s, idx %d", iface, ifindex);

#ifdef AF_INET6
	if (sg->grp.ss_family == AF_INET6)
		proto = IPPROTO_IPV6;
	else
#endif<commit_msg>Validate receiving interface before attempting socket/join<commit_after>/* Join multicast group(s) and display receive progress
 *
 * Copyright (C) 2004       <NAME> <dlstevens()us!ibm!com>
 * Copyright (C) 2008-2020  <NAME> <troglobit()gmail!com>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include "config.h"

#include <errno.h>
#include <poll.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "mcjoin.h"

int num_joins = 0;

static int alloc_socket(inet_addr_t group)
{
	inet_addr_t ina = { 0 };
	int sd, val, proto;

	ina.ss_family = group.ss_family;
	inet_addr_set_port(&ina, inet_addr_get_port(&group));

#ifdef AF_INET6
	if (group.ss_family == AF_INET6)
		proto = IPPROTO_IPV6;
	else
#endif
		proto = IPPROTO_IP;

	sd = socket(group.ss_family, SOCK_DGRAM, IPPROTO_UDP);
	if (sd < 0) {
		ERROR("Failed opening socket(): %s", strerror(errno));
		return -1;
	}

	val = 1;
#ifdef SO_REUSEPORT
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val)))
		ERROR("Failed enabling SO_REUSEPORT: %s", strerror(errno));
#endif
	if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)))
		ERROR("Failed enabling SO_REUSEADDR: %s", strerror(errno));

#ifdef AF_INET6
	if (proto == IPPROTO_IPV6) {
		if (setsockopt(sd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)))
			ERROR("Failed enabling IPV6_RECVPKTINFO: %s", strerror(errno));
#ifdef IPV6_MULTICAST_ALL
		val = 0;
		if (setsockopt(sd, proto, IPV6_MULTICAST_ALL, &val, sizeof(val)))
			ERROR("Failed disabling IP_MULTICAST_ALL: %s", strerror(errno));
#endif
	}
#endif
	else {
		val = 1;
#if defined(IP_PKTINFO) || !defined(IP_RECVDSTADDR)
		if (setsockopt(sd, SOL_IP, IP_PKTINFO, &val, sizeof(val)))
			ERROR("Failed enabling IP_PKTINFO: %s", strerror(errno));
#elif defined(IP_RECVDSTADDR)
		if (setsockopt(sd, proto, IP_RECVDSTADDR, &val, sizeof(val)))
			ERROR("Failed enabling IP_RECVDSTADDR: %s", strerror(errno));
#endif
#ifdef IP_MULTICAST_ALL
		val = 0;
		if (setsockopt(sd, proto, IP_MULTICAST_ALL, &val, sizeof(val)))
			ERROR("Failed disabling IP_MULTICAST_ALL: %s", strerror(errno));
#endif
	}

	if (bind(sd, (struct sockaddr *)&ina, inet_addrlen(&ina))) {
		ERROR("Failed binding to socket: %s", strerror(errno));
		close(sd);
		return -1;
	}

	return sd;
}

static int join_group(struct gr *sg)
{
	struct group_source_req gsr;
	struct group_req gr;
	char src[INET_ADDRSTR_LEN] = "*";
	char grp[INET_ADDRSTR_LEN];
	size_t len;
	void *arg;
	int ifindex;
	int sd, op, proto;

	ifindex = if_nametoindex(iface);
	if (!ifindex) {
		ERROR("invalid interface: %s", *iface ? iface : "(nil)");
		return 1;
	}
	DEBUG("Added iface %s, ifindex %d", iface, ifindex);

	sd = alloc_socket(sg->grp);
	if (sd < 0) {
		DEBUG("Failed allocating socket.");
		return 1;
	}

#ifdef AF_INET6
	if (sg->grp.ss_family == AF_INET6)
		proto = IPPROTO_IPV6;
	else
#endif
{'fraction_non_alphanumeric': 0.12733228884774248, 'fraction_numerical': 0.010397379290699331, 'mean_word_length': 4.960950764006792, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2431891', 'n_tokens_mistral': 2760, 'n_tokens_neox': 2571, 'n_words': 752}