示例#1
0
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;
}
示例#2
0
static void CountSSMLeave(const address &group, const address &source) {
	address source_addr;
	char tmp[64], tmp2[64];

	GroupMap::iterator g = groupMap.find(group);
	assert(g != groupMap.end());
	source_addr.set_family(source.family());
	source_addr.copy_address(source);
	source_addr.set_port(0);
	SourceMap::iterator s = g->second.find(source_addr);
	assert(s != g->second.end());
	SourceSet::iterator ss = s->second.find(source);
	if (ss == s->second.end()) {
		return;
	}
	if (verbose)
		info("Removing beacon %s from (%s, %s)", source.to_string(tmp, sizeof(tmp)),
		     source_addr.to_string(tmp2, sizeof(tmp2)),
		     group.to_string(tmp2, sizeof(tmp2)));
	s->second.erase(ss);
	if (s->second.empty()) {
		if (verbose)
			info("No more beacons for (%s, %s), leaving group",
			     source_addr.to_string(tmp, sizeof(tmp)),
			     group.to_string(tmp2, sizeof(tmp2)));
		SSMLeave(ssmMcastSock,group, source_addr);
		g->second.erase(s);
	}
	if (g->second.empty()) {
		if (verbose)
			info("No more sources, unregistering group %s, ", group.to_string(tmp, sizeof(tmp)));
		groupMap.erase(g);
	}
}
示例#3
0
int SendTo(int sock, const uint8_t *buffer, int len, const address &from, const address &to) {
#ifdef IPV6_PKTINFO
	if (from.family() == AF_INET6) {
		uint8_t ctlbuf[CMSG_SPACE(sizeof(in6_pktinfo))];

		cmsghdr *chdr = (cmsghdr *)ctlbuf;
		chdr->cmsg_len = CMSG_LEN(sizeof(in6_pktinfo));
		chdr->cmsg_level = IPPROTO_IPV6;
		chdr->cmsg_type = IPV6_PKTINFO;

		in6_pktinfo *info = (in6_pktinfo *)CMSG_DATA(chdr);
		info->ipi6_addr = from.v6()->sin6_addr;
		info->ipi6_ifindex = 0;

		msghdr msg;
		iovec iov;

		msg.msg_name = (char *)to.saddr();
		msg.msg_namelen = to.addrlen();
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
		msg.msg_control = (char *)ctlbuf;
		msg.msg_controllen = sizeof(ctlbuf);
		msg.msg_flags = 0;

		iov.iov_base = (char *)buffer;
		iov.iov_len = len;

		return sendmsg(sock, &msg, 0);
	}
#endif
	return sendto(sock, buffer, len, 0, to.saddr(), to.addrlen());
}
示例#4
0
static void CountSSMJoin(const address &group, const address &source) {
	address source_addr;
	char tmp[64], tmp2[64], tmp3[64];
	
	source_addr.set_family(source.family());
	source_addr.copy_address(source);
	source_addr.set_port(0);
	GroupMap::iterator g = groupMap.find(group);
	if (g == groupMap.end()) {
		if (verbose) 
			info("Registering SSM group %s", group.to_string(tmp, sizeof(tmp)));
		g = groupMap.insert(std::make_pair(group, SourceMap())).first;
	}
	SourceMap::iterator s = g->second.find(source_addr);
	if (s == g->second.end()) {
		if (verbose)
			info("Joining (%s, %s)", source_addr.to_string(tmp, sizeof(tmp)),
			     group.to_string(tmp2, sizeof(tmp2)));
		if (SSMJoin(ssmMcastSock, group, source_addr) < 0) {
			if (verbose)
				info("Join failed, reason: %s", strerror(errno));
			return;
		} else {
			s = g->second.insert(std::make_pair(source_addr, SourceSet())).first;
		}
	} 
	SourceSet::iterator ss = s->second.find(source);
	if (ss == s->second.end()) {
		if (verbose)
			info("Adding beacon %s to (%s, %s)", source.to_string(tmp, sizeof(tmp)),
			     source_addr.to_string(tmp2, sizeof(tmp2)),
			     group.to_string(tmp3, sizeof(tmp3)));
		s->second.insert(source);
	}
}
示例#5
0
bool RequireToAddress(int sock, const address &addr) {
#ifdef IPV6_PKTINFO
	if (addr.family() == AF_INET6) {
		int on = 1;
		return setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) == 0;
	}
#endif

	return true;
}
示例#6
0
bool address::copy_address(const address &source) {
	if (family() != source.family())
		return false;

	if (stor.ss_family == AF_INET6)
		v6()->sin6_addr = source.v6()->sin6_addr;
	else
		v4()->sin_addr = source.v4()->sin_addr;

	return true;
}
示例#7
0
address get_local_address_for(const address &remote)
{
	int tmpSock = socket(remote.family(), SOCK_DGRAM, 0);
	if (tmpSock < 0) {
		perror("Failed to create socket to discover local addr");
		exit(-1);
	}

	if (connect(tmpSock, remote.saddr(), remote.addrlen()) != 0) {
		perror("Failed to connect multicast socket");
		exit(-1);
	}

	address result(remote.family());
	if (result.fromsocket(tmpSock) < 0) {
		perror("getsockname");
		exit(-1);
	}

	close(tmpSock);
	return result;
}
示例#8
0
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));
	}
}
示例#9
0
int SetupSocket(const address &addr, bool shouldbind, bool ssm) {
	int af_family = addr.family();
	int level = addr.optlevel();

	int sock = socket(af_family, SOCK_DGRAM, 0);
	if (sock < 0) {
		perror("Failed to create multicast socket");
		return -1;
	}

	int on = 1;

	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) != 0) {
		perror("setsockopt");
		return -1;
	}

	if (shouldbind) {
		if (bind(sock, addr.saddr(), addr.addrlen()) != 0) {
			perror("Failed to bind multicast socket");
			return -1;
		}
	}

#ifdef SO_TIMESTAMP
	if (setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) != 0) {
		perror("setsockopt(SO_TIMESTAMP)");
		return -1;
	}
#endif

	int type = level == IPPROTO_IPV6 ?
#ifdef IPV6_RECVHOPLIMIT
				IPV6_RECVHOPLIMIT
#else
				IPV6_HOPLIMIT
#endif
				:
#ifdef IP_RECVTTL
				IP_RECVTTL;
#else
				IP_TTL;
#endif

	if (setsockopt(sock, level, type, &on, sizeof(on)) != 0) {
		perror("receiving hop limit/ttl setsockopt()");
		return -1;
	}

	if (!SetHops(sock, addr, defaultTTL)) {
		perror("SetHops");
		return -1;
	}

	if (!ssm && addr.is_multicast()) {
		if (MulticastListen(sock, addr) != 0) {
			perror("Failed to join multicast group");
			return -1;
		}
	}

	return sock;
}
示例#10
0
int main(int argc, char **argv) {
	int res;

	srand(time(NULL));

	char tmp[256];
	if (gethostname(tmp, sizeof(tmp)) != 0) {
		perror("Failed to get hostname");
		return -1;
	}

	beaconName = tmp;

	parse_arguments(argc, argv);

	MulticastStartup();

	if (beaconName.empty())
		fatal("No name supplied, check `dbeacon -h`.");

	if (!probeAddrLiteral.empty()) {
		if (!probeAddr.parse(probeAddrLiteral.c_str(), true))
			return -1;

		probeAddr.to_string(sessionName, sizeof(sessionName));

		if (!probeAddr.is_multicast())
			fatal("Specified probe addr (%s) is not of a multicast group.",
					sessionName);

		if (adminContact.empty())
			fatal("No administration contact supplied, check `dbeacon -h`.");

		mcastListen.push_back(ContentDesc(probeAddr, false));

		insert_event(SENDING_EVENT, 100);
		insert_event(REPORT_EVENT, 10000);
		insert_event(MAP_REPORT_EVENT, 30000);
		insert_event(WEBSITE_REPORT_EVENT, 120000);

		redist.push_back(probeAddr);

		if (useSSM) {
			if (probeSSMAddrLiteral.empty()) {
				int family = forceFamily;

				if (family == AF_UNSPEC) {
					family = probeAddr.family();
				}
				if (family == AF_INET) {
					probeSSMAddrLiteral = defaultIPv4SSMChannel;
				} else {
					probeSSMAddrLiteral = defaultIPv6SSMChannel;
				}
			}

			if (!ssmProbeAddr.parse(probeSSMAddrLiteral.c_str(), true)) {
				fatal("Bad address format for SSM channel.");
			} else if (!ssmProbeAddr.is_unspecified()) {
				insert_event(SSM_SENDING_EVENT, 100);
				insert_event(SSM_REPORT_EVENT, 15000);

				if (listenForSSM) {
					mcastListen.push_back(ContentDesc(ssmProbeAddr, true));
				}
			}
		}
	} else {
		if (mcastListen.empty())
			fatal("Nothing to do, check `dbeacon -h`.");
		else
			strcpy(sessionName, beaconName.c_str());
	}

	address local;
	local.set_family(probeAddr.family());

	mcastSock = SetupSocket(local, false, false);
	if (mcastSock < 0)
		return -1;

	if (beaconUnicastAddr.is_unspecified())
		beaconUnicastAddr = get_local_address_for(probeAddr);

	if (bind(mcastSock, beaconUnicastAddr.saddr(), beaconUnicastAddr.addrlen()) != 0) {
		perror("Failed to bind local socket");
		return -1;
	}

	if (beaconUnicastAddr.fromsocket(mcastSock) < 0) {
		perror("getsockname");
		return -1;
	}

	for (McastListen::const_iterator i = mcastListen.begin();
			i != mcastListen.end(); ++i) {
		int sock = SetupSocket(i->first, true, i->second);
		if (sock < 0)
			return -1;

		if (i->second) {
			ListenTo(sock, handle_ssm);
			ssmMcastSock = sock;
		} else {
			ListenTo(sock, handle_asm);
		}
	}

	if (useSSMPing) {
		if (SetupSSMPing() < 0)
			d_log(LOG_ERR, "Failed to setup SSM Ping.");
		else
			flags |= SSMPING_CAPABLE;
	}

	if (IsSSMEnabled()) {
		flags |= SSM_CAPABLE;

		uint64_t now = get_timestamp();
		for (vector<address>::const_iterator i = ssmBootstrap.begin();
				i != ssmBootstrap.end(); ++i)
			getSource(*i, 0, now, 0, false);
	} else if (!ssmBootstrap.empty())
		d_log(LOG_WARNING, "Tried to bootstrap using SSM when SSM is not enabled.");

	if (daemonize || use_syslog) {
		use_syslog = true;
		openlog("dbeacon", LOG_NDELAY | LOG_PID, LOG_DAEMON);
	}

	past_init = true;

	if (daemonize) {
		if (dbeacon_daemonize(pidfile)) {
			perror("Failed to daemon()ize.");
			return -1;
		}
	}

	// Init timer events
	insert_event(GARBAGE_COLLECT_EVENT, 30000);

	if (!dumpFile.empty())
		insert_event(DUMP_EVENT, dumpInterval * 1000);

	insert_event(DUMP_BW_EVENT, 10000);

	if (dumpBwReport)
		insert_event(DUMP_BIG_BW_EVENT, 600000);

	info("Local name is `%s` [Beacon group: %s, Local address: %s]",
		beaconName.c_str(), sessionName, beaconUnicastAddr.to_string(tmp, sizeof(tmp), false));

	send_report(WEBSITE_REPORT_EVENT);

	signal(SIGUSR1, dumpBigBwStats);
	signal(SIGINT, sendLeaveReport);
	signal(SIGTERM, sendLeaveReport);

	signal(SIGCHLD, waitForMe); // bloody fork, we dont want to wait for thee

	startTime = lastDumpBwTS = lastDumpDumpBwTS = get_timestamp();

	while (1) {
		fd_set readset;
		timeval eventm;

		FD_ZERO(&readset);

		for (McastSocks::const_iterator i = mcastSocks.begin();
				i != mcastSocks.end(); ++i)
			FD_SET(i->first, &readset);

		next_event(&eventm);

		res = select(mcastSocks.rbegin()->first + 1, &readset, 0, 0, &eventm);

		if (res < 0) {
			if (errno == EINTR)
				continue;
			fatal("Select failed: %s", strerror(errno));
		} else {
			for (McastSocks::const_iterator i = mcastSocks.begin();
					res > 0 && i != mcastSocks.end(); ++i) {
				if (FD_ISSET(i->first, &readset)) {
					handle_mcast(*i);
					res--;
				}
			}

			handle_event();
		}
	}

	return 0;
}