<commit_before>/*
 * dbeacon, a Multicast Beacon
 *   dbeacon_posix.cpp
 *
 * Copyright (C) 2005 <NAME>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors:	<NAME> <<EMAIL>>
 */

#include "dbeacon.h"
#include "msocket.h"
#include "address.h"
#include "ptime.h"

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#include <unistd.h>

int _McastListenNewAPI(int sock, const address &grpaddr);
int _McastListenOldAPI(int sock, const address &grpaddr);

static int (*_McastListen)(int, const address &) = _McastListenOldAPI;

#if !defined(MCAST_JOIN_GROUP)

#define MCAST_JOIN_GROUP 42
#define MCAST_JOIN_SOURCE_GROUP 46
#define MCAST_LEAVE_SOURCE_GROUP 47

struct group_req {
	uint32_t gr_interface;
	struct sockaddr_storage gr_group;
};

struct group_source_req {
	uint32_t gsr_interface;
	struct sockaddr_storage gsr_group;
	struct sockaddr_storage gsr_source;
};

#endif

#if !defined MCAST_FILTER
#define MCAST_FILTER	48

struct group_filter {
	uint32_t gf_interface;
	struct sockaddr_storage gf_group;
	uint32_t gf_fmode;
	uint32_t gf_numsrc;
	struct sockaddr_storage gf_slist[1];
};

#endif

static bool set_address(sockaddr_storage &t, const address &addr) {
	if (addr.family() == AF_INET)
		memcpy(&t, addr.v4(), addr.addrlen());
	else if (addr.family() == AF_INET6)
		memcpy(&t, addr.v6(), addr.addrlen());
	else
		return false;
	return true;
}

void MulticastStartup() {
	int sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock > 0) {
		group_filter flt;
		memset(&flt, 0, sizeof(flt));
		socklen_t fltlen = sizeof(flt);

		// Check if OS supports MCAST_FILTER

		if (getsockopt(sock, IPPROTO_IP, MCAST_FILTER, &flt, &fltlen) == 0 && errno != ENOPROTOOPT) {
			if (verbose) {
				fprintf(stderr, "Using new Multicast Filter API\n");
			}

			_McastListen = _McastListenNewAPI;
		}

		close(sock);
	}
}

int _McastListenNewAPI(int sock, const address &grpaddr) {
	struct group_req grp;

	memset(&grp, 0, sizeof(grp));
	grp.gr_interface = mcastInterface;

	set_address(grp.gr_group, grpaddr);

	return setsockopt(sock, grpaddr.optlevel(), MCAST_JOIN_GROUP, &grp, sizeof(grp));
}

int _McastListenOldAPI(int sock, const address &grpaddr) {
	if (grpaddr.family() == AF_INET6) {
		ipv6_mreq mreq;
		mreq.ipv6mr_interface = mcastInterface;
		mreq.ipv6mr_multiaddr = grpaddr.v6()->sin6_addr;

		return setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
	} else {
		ip_mreq mreq;
		memset(&mreq, 0, sizeof(mreq));
		// Specifying the interface doesn't work, there's ip_mreqn in linux..
		// but what about other OSs? -hugo
		mreq.imr_multiaddr = grpaddr.v4()->sin_addr;

		return setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
	}
}

int MulticastListen(int sock, const address &grpaddr) {
	return (*_McastListen)(sock, grpaddr);
}

static int SSMJoinLeave(int sock, int type, const address &grpaddr, const address &srcaddr) {
	struct group_source_req req;
	memset(&req, 0, sizeof(req));

	req.gsr_interface = mcastInterface;

	set_address(req.gsr_group, grpaddr);
	set_address(req.gsr_source, srcaddr);

	return setsockopt(sock, srcaddr.optlevel(), type, &req, sizeof(req));
}

int SSMJoin(int sock, const address &grpaddr, const address &srcaddr) {
	return SSMJoinLeave(sock, MCAST_JOIN_SOURCE_GROUP, grpaddr, srcaddr);
}

int SSMLeave(int sock, const address &grpaddr, const address &srcaddr) {
	return SSMJoinLeave(sock, MCAST_LEAVE_SOURCE_GROUP, grpaddr, srcaddr);
}

int SetupSocket(const address &addr, bool shouldbind, bool ssm) {<commit_msg>damn you glibcs and your missing declarations between versions<commit_after>/*
 * dbeacon, a Multicast Beacon
 *   dbeacon_posix.cpp
 *
 * Copyright (C) 2005 <NAME>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors:	<NAME> <<EMAIL>>
 */

#include "dbeacon.h"
#include "msocket.h"
#include "address.h"
#include "ptime.h"

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <netdb.h>
#include <unistd.h>

int _McastListenNewAPI(int sock, const address &grpaddr);
int _McastListenOldAPI(int sock, const address &grpaddr);

static int (*_McastListen)(int, const address &) = _McastListenOldAPI;

#ifndef MCAST_JOIN_GROUP
#define MCAST_JOIN_GROUP 42
#endif

#ifndef MCAST_JOIN_SOURCE_GROUP
#define MCAST_JOIN_SOURCE_GROUP 46
#define MCAST_LEAVE_SOURCE_GROUP 47
#endif

#ifndef MCAST_FILTER
#define MCAST_FILTER	48
#endif

// Since some GLIBCs include this definitions, and others don't (i'm not even
// talking about BSDs) we instead define them localy to avoid definition colisions

struct _loc_group_req {
	uint32_t gr_interface;
	struct sockaddr_storage gr_group;
};

struct _loc_group_source_req {
	uint32_t gsr_interface;
	struct sockaddr_storage gsr_group;
	struct sockaddr_storage gsr_source;
};

struct _loc_group_filter {
	uint32_t gf_interface;
	struct sockaddr_storage gf_group;
	uint32_t gf_fmode;
	uint32_t gf_numsrc;
	struct sockaddr_storage gf_slist[1];
};

static bool set_address(sockaddr_storage &t, const address &addr) {
	if (addr.family() == AF_INET)
		memcpy(&t, addr.v4(), addr.addrlen());
	else if (addr.family() == AF_INET6)
		memcpy(&t, addr.v6(), addr.addrlen());
	else
		return false;
	return true;
}

void MulticastStartup() {
	int sock = socket(AF_INET, SOCK_DGRAM, 0);
	if (sock > 0) {
		_loc_group_filter flt;
		memset(&flt, 0, sizeof(flt));
		socklen_t fltlen = sizeof(flt);

		// Check if OS supports MCAST_FILTER

		if (getsockopt(sock, IPPROTO_IP, MCAST_FILTER, &flt, &fltlen) == 0
				&& errno != ENOPROTOOPT) {
			if (verbose) {
				fprintf(stderr, "Using new Multicast Filter API\n");
			}

			_McastListen = _McastListenNewAPI;
		}

		close(sock);
	}
}

int _McastListenNewAPI(int sock, const address &grpaddr) {
	_loc_group_req grp;

	memset(&grp, 0, sizeof(grp));
	grp.gr_interface = mcastInterface;

	set_address(grp.gr_group, grpaddr);

	return setsockopt(sock, grpaddr.optlevel(), MCAST_JOIN_GROUP, &grp, sizeof(grp));
}

int _McastListenOldAPI(int sock, const address &grpaddr) {
	if (grpaddr.family() == AF_INET6) {
		ipv6_mreq mreq;
		mreq.ipv6mr_interface = mcastInterface;
		mreq.ipv6mr_multiaddr = grpaddr.v6()->sin6_addr;

		return setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq));
	} else {
		ip_mreq mreq;
		memset(&mreq, 0, sizeof(mreq));
		// Specifying the interface doesn't work, there's ip_mreqn in linux..
		// but what about other OSs? -hugo
		mreq.imr_multiaddr = grpaddr.v4()->sin_addr;

		return setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
	}
}

int MulticastListen(int sock, const address &grpaddr) {
	return (*_McastListen)(sock, grpaddr);
}

static int SSMJoinLeave(int sock, int type, const address &grpaddr, const address &srcaddr) {
	_loc_group_source_req req;
	memset(&req, 0, sizeof(req));

	req.gsr_interface = mcastInterface;

	set_address(req.gsr_group, grpaddr);
	set_address(req.gsr_source, srcaddr);

	return setsockopt(sock, srcaddr.optlevel(), type, &req, sizeof(req));
}

int SSMJoin(int sock, const address &grpaddr, const address &srcaddr) {
	return SSMJoinLeave(sock, MCAST_JOIN_SOURCE_GROUP, grpaddr, srcaddr);
}

int SSMLeave(int sock, const address &grpaddr, const address &srcaddr) {
	return SSMJoinLeave(sock, MCAST_LEAVE_SOURCE_GROUP, grpaddr, srcaddr);
}

int SetupSocket(const address &addr, bool shouldbind, bool ssm) {
{'fraction_non_alphanumeric': 0.10969358696890306, 'fraction_numerical': 0.012985533659870145, 'mean_word_length': 5.03021978021978, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 33, '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': '1409080', 'n_tokens_mistral': 3317, 'n_tokens_neox': 3187, 'n_words': 898}