Beispiel #1
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);
	}
}
Beispiel #2
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);
	}
}
Beispiel #3
0
    std::string to_string()const
    {
        std::string buf;
        std::stringstream sbuf;

        buf = ip.to_string();
        buf += "/";
        sbuf << mask.bits();
        buf += sbuf.str();

        return buf;
    }
Beispiel #4
0
void removeSource(const address &baddr, bool timeout) {
	Sources::iterator i = sources.find(baddr);
	if (i != sources.end()) {
		if (verbose) {
			char tmp[64];

			if (i->second.identified) {
				info("Removing source %s [%s]%s",
					baddr.to_string(tmp, sizeof(tmp)), i->second.name.c_str(),
					(timeout ? " by Timeout" : ""));
			} else {
				info("Removing source %s%s",
					baddr.to_string(tmp, sizeof(tmp)), (timeout ? " by Timeout" : ""));
			}
		}

		if (IsSSMEnabled())
			CountSSMLeave(ssmProbeAddr, baddr);

		sources.erase(i);
	}
}
Beispiel #5
0
std::string ipport_to_string(address const& addr,int port)
{
	error_code ec;
	std::string straddr = addr.to_string(ec);
	std::string ret;
	ret.reserve(straddr.length()+10);
	if (addr.is_v6())
	{
		ret += '[';
		ret += straddr;
		ret += ']';
		ret += ':';
		ret += boost::lexical_cast<std::string>(port);
	}
	else
	{
		ret += straddr;
		ret += ':';
		ret += boost::lexical_cast<std::string>(port);
	}
	return ret;
}
Beispiel #6
0
void handle_nmsg(const address &from, uint64_t recvdts, int ttl, uint8_t *buff, int len, bool ssm) {
	if (len < 4)
		return;

	if (ntohs(*((uint16_t *)buff)) != 0xbeac)
		return;

	if (buff[2] != PROTO_VER)
		return;

	uint64_t now = get_timestamp();

	if (buff[3] == 0) {
		if (len == 12) {
			uint32_t seq = read_u32(buff + 4);
			uint32_t ts = read_u32(buff + 8);
			getSource(from, 0, now, recvdts, true).update(ttl, seq, ts, now, recvdts, ssm);
		}
		return;
	} else if (buff[3] == 1) {
		if (len < 5)
			return;

		beaconSource &src = getSource(from, 0, now, recvdts, true);

		src.sttl = buff[4];

		len -= 5;

		for (uint8_t *hd = tlv_begin(buff + 5, len); hd; hd = tlv_next(hd, len)) {
			if (verbose > 4) {
				char tmp[64];
				from.to_string(tmp, sizeof(tmp));
				fprintf(stderr, "Parsing TLV (%i, %i) for %s [len is now %i]\n", (int)hd[0], (int)hd[1], tmp, len);
			}

			if (hd[0] == T_BEAC_NAME) {
				string name;
				if (check_string((char *)hd + 2, hd[1], name))
					src.setName(name);
			} else if (hd[0] == T_ADMIN_CONTACT) {
				check_string((char *)hd + 2, hd[1], src.adminContact);
			} else if (hd[0] == T_SOURCE_INFO || hd[0] == T_SOURCE_INFO_IPv4) {
				int blen = hd[0] == T_SOURCE_INFO ? 18 : 6;

				if (hd[1] < blen)
					continue;

				address addr;

				if (hd[0] == T_SOURCE_INFO) {
					sockaddr_in6 *a6 = (sockaddr_in6 *)&addr;

					a6->sin6_family = AF_INET6;

					memcpy(&a6->sin6_addr, hd + 2, sizeof(in6_addr));
					memcpy(&a6->sin6_port, hd + 18, sizeof(uint16_t));
				} else {
					sockaddr_in *a4 = (sockaddr_in *)&addr;

					a4->sin_family = AF_INET;

					memcpy(&a4->sin_addr, hd + 2, sizeof(in_addr));
					memcpy(&a4->sin_port, hd + 6, sizeof(uint16_t));
				}

				beaconExternalStats &stats = src.getExternal(addr, now, recvdts);

				int plen = hd[1] - blen;
				for (uint8_t *pd = tlv_begin(hd + 2 + blen, plen); pd; pd = tlv_next(pd, plen)) {
					if (pd[0] == T_BEAC_NAME) {
						if (check_string((char *)pd + 2, pd[1], stats.name)) {
							stats.identified = !stats.name.empty();
						}
					} else if (pd[0] == T_ADMIN_CONTACT) {
						check_string((char *)pd + 2, pd[1], stats.contact);
					} else if (pd[0] == T_ASM_STATS || pd[0] == T_SSM_STATS) {
						Stats *st = (pd[0] == T_ASM_STATS ? &stats.ASM : &stats.SSM);

						if (!read_tlv_stats(pd, stats, *st))
							break;
						st->lastupdate = now;
					}
				}

				// trigger local SSM join
				if (!addr.is_equal(beaconUnicastAddr)) {
					beaconSource &t = getSource(addr, stats.identified ? stats.name.c_str() : 0, now, recvdts, false);
					if (t.adminContact.empty())
						t.adminContact = stats.contact;
				}
			} else if (hd[0] == T_WEBSITE_GENERIC || hd[0] == T_WEBSITE_LG || hd[0] == T_WEBSITE_MATRIX) {
				string url;
				if (check_string((char *)hd + 2, hd[1], url)) {
					src.webSites[hd[0]] = url;
				}
			} else if (hd[0] == T_CC) {
				if (hd[1] == 2) {
					src.CC = string((char *)hd + 2, 2);
				}
			} else if (hd[0] == T_SOURCE_FLAGS) {
				if (hd[1] == 4)
					src.Flags = read_u32(hd + 2);
			} else if (hd[0] == T_LEAVE) {
				removeSource(from, false);
				break;
			}
		}
	}
}
void run_test(HandleAlerts const& on_alert, Test const& test)
{
    using namespace libtorrent;

    using asio::ip::address;
    address const peer0 = addr("50.0.0.1");
    address const peer1 = addr("50.0.0.2");

    // setup the simulation
    sim::default_config network_cfg;
    sim::simulation sim{network_cfg};
    sim::asio::io_service ios0 { sim, peer0 };
    sim::asio::io_service ios1 { sim, peer1 };

    lt::session_proxy zombie[2];

    // setup settings pack to use for the session (customization point)
    lt::settings_pack pack = settings();

    // disable utp by default
    pack.set_bool(settings_pack::enable_outgoing_utp, false);
    pack.set_bool(settings_pack::enable_incoming_utp, false);

    // disable encryption by default
    pack.set_bool(settings_pack::prefer_rc4, false);
    pack.set_int(settings_pack::in_enc_policy, settings_pack::pe_disabled);
    pack.set_int(settings_pack::out_enc_policy, settings_pack::pe_disabled);
    pack.set_int(settings_pack::allowed_enc_level, settings_pack::pe_plaintext);

    pack.set_str(settings_pack::listen_interfaces, peer0.to_string() + ":6881");

    // create session
    std::shared_ptr<lt::session> ses[2];
    ses[0] = std::make_shared<lt::session>(pack, ios0);

    pack.set_str(settings_pack::listen_interfaces, peer1.to_string() + ":6881");
    ses[1] = std::make_shared<lt::session>(pack, ios1);

    // only monitor alerts for session 0 (the downloader)
    print_alerts(*ses[0], [=](lt::session& ses, lt::alert const* a) {
        if (auto ta = alert_cast<lt::torrent_added_alert>(a))
        {
            ta->handle.connect_peer(lt::tcp::endpoint(peer1, 6881));
        }
        on_alert(ses, a);
    });

    print_alerts(*ses[1]);

    // the first peer is a downloader, the second peer is a seed
    lt::add_torrent_params params = create_torrent(1);
    params.flags &= ~lt::add_torrent_params::flag_auto_managed;
    params.flags &= ~lt::add_torrent_params::flag_paused;

    params.save_path = save_path(0);
    ses[0]->async_add_torrent(params);

    params.save_path = save_path(1);
    ses[1]->async_add_torrent(params);

    sim::timer t(sim, lt::seconds(60), [&](boost::system::error_code const& ec)
    {
        test(ses);

        // shut down
        int idx = 0;
        for (auto& s : ses)
        {
            zombie[idx++] = s->abort();
            s.reset();
        }
    });

    sim.run();
}
Beispiel #8
0
	inline std::string print_address(address const& addr)
	{
		error_code ec;
		return addr.to_string(ec);
	}
Beispiel #9
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;
}
Beispiel #10
0
void do_dump() {
	string tmpf = dumpFile;
	tmpf += ".working";

	FILE *fp = fopen(tmpf.c_str(), "w");
	if (!fp)
		return;

	uint64_t now = get_timestamp();
	uint64_t diff = now - lastDumpDumpBwTS;
	lastDumpDumpBwTS = now;

	double rxRate = dumpBytesReceived * 8 / ((double)diff);
	double txRate = dumpBytesSent * 8 / ((double)diff);
	dumpBytesReceived = 0;
	dumpBytesSent = 0;

	fprintf(fp, "<beacons rxrate=\"%.2f\" txrate=\"%.2f\" versioninfo=\"%s\">\n", rxRate, txRate, versionInfo);

	fprintf(fp, "<group addr=\"%s\"", sessionName);

	char tmp[64];

	if (IsSSMEnabled())
		fprintf(fp, " ssmgroup=\"%s\"", ssmProbeAddr.to_string(tmp, sizeof(tmp)));

	fprintf(fp, " int=\"%.2f\">\n", beacInt);

	if (!probeAddr.is_unspecified()) {
		fprintf(fp, "\t<beacon name=\"%s\" addr=\"%s\"", beaconName.c_str(),
				beaconUnicastAddr.to_string(tmp, sizeof(tmp)));
		if (!adminContact.empty())
			fprintf(fp, " contact=\"%s\"", adminContact.c_str());
		if (!twoLetterCC.empty())
			fprintf(fp, " country=\"%s\"", twoLetterCC.c_str());
		fprintf(fp, " age=\"%lu\" lastupdate=\"0\" rxlocal=\"true\">\n", (now - startTime) / 1000);

		for (uint32_t k = 0; k < KnownFlags; k++) {
			if (flags & (1 << k)) {
				fprintf(fp, "\t\t<flag name=\"%s\" value=\"true\" />\n", Flags[k]);
			}
		}

		for (WebSites::const_iterator j = webSites.begin(); j != webSites.end(); j++) {
			const char *typnam = j->first == T_WEBSITE_GENERIC ?
				"generic" : (j->first == T_WEBSITE_LG ? "lg" : "matrix");
			fprintf(fp, "\t\t<website type=\"%s\" url=\"%s\" />\n", typnam, j->second.c_str());
		}

		fprintf(fp, "\t\t<sources>\n");

		for (Sources::const_iterator i = sources.begin(); i != sources.end(); i++) {
			fprintf(fp, "\t\t\t<source addr=\"%s\"", i->first.to_string(tmp, sizeof(tmp)));
			if (i->second.identified) {
				fprintf(fp, " name=\"%s\"", i->second.name.c_str());
				if (!i->second.adminContact.empty())
					fprintf(fp, " contact=\"%s\"", i->second.adminContact.c_str());
			}

			if (!i->second.CC.empty())
				fprintf(fp, " country=\"%s\"", i->second.CC.c_str());

			fprintf(fp, " age=\"%lu\"", (now - i->second.creation) / 1000);
			fprintf(fp, " lastupdate=\"%lu\">\n", (now - i->second.lastevent) / 1000);

			if (i->second.ASM.s.valid)
				dumpStats(fp, "asm", i->second.ASM.s, now, i->second.sttl, true);

			if (i->second.SSM.s.valid)
				dumpStats(fp, "ssm", i->second.SSM.s, now, i->second.sttl, true);

			fprintf(fp, "\t\t\t</source>\n");
		}

		fprintf(fp, "\t\t</sources>\n");
		fprintf(fp, "\t</beacon>\n");
		fprintf(fp, "\n");
	}

	for (Sources::const_iterator i = sources.begin(); i != sources.end(); i++) {
		fprintf(fp, "\t<beacon");
		if (i->second.identified) {
			fprintf(fp, " name=\"%s\"", i->second.name.c_str());
			if (!i->second.adminContact.empty())
				fprintf(fp, " contact=\"%s\"", i->second.adminContact.c_str());
		}
		fprintf(fp, " addr=\"%s\"", i->first.to_string(tmp, sizeof(tmp)));
		fprintf(fp, " age=\"%lu\"", (now - i->second.creation) / 1000);
		fprintf(fp, " rxlocal=\"%s\"", i->second.rxlocal(now) ? "true" : "false");
		fprintf(fp, " lastupdate=\"%lu\">\n", (now - i->second.lastevent) / 1000);

		for (uint32_t k = 0; k < KnownFlags; k++) {
			if (i->second.Flags & (1 << k)) {
				fprintf(fp, "\t\t<flag name=\"%s\" value=\"true\" />\n", Flags[k]);
			}
		}

		for (WebSites::const_iterator j = i->second.webSites.begin();
						j != i->second.webSites.end(); j++) {
			const char *typnam = j->first == T_WEBSITE_GENERIC ?
				"generic" : (j->first == T_WEBSITE_LG ? "lg" : "matrix");
			fprintf(fp, "\t\t<website type=\"%s\" url=\"%s\" />\n",
						typnam, j->second.c_str());
		}

		fprintf(fp, "\t\t<sources>\n");

		for (beaconSource::ExternalSources::const_iterator j = i->second.externalSources.begin();
				j != i->second.externalSources.end(); j++) {
			fprintf(fp, "\t\t\t<source");
			if (j->second.identified) {
				fprintf(fp, " name=\"%s\"", j->second.name.c_str());
				fprintf(fp, " contact=\"%s\"", j->second.contact.c_str());
			}
			fprintf(fp, " addr=\"%s\"", j->first.to_string(tmp, sizeof(tmp)));
			fprintf(fp, " age=\"%u\">\n", j->second.age);
			if (j->second.ASM.valid)
				dumpStats(fp, "asm", j->second.ASM, now, i->second.sttl, false);
			if (j->second.SSM.valid)
				dumpStats(fp, "ssm", j->second.SSM, now, i->second.sttl, false);
			fprintf(fp, "\t\t\t</source>\n");
		}

		fprintf(fp, "\t\t</sources>\n");
		fprintf(fp, "\t</beacon>\n");
	}

	fprintf(fp, "</group>\n</beacons>\n");

	fclose(fp);

	rename(tmpf.c_str(), dumpFile.c_str());

	if (!launchSomething.empty())
		doLaunchSomething();
}