<commit_before>/*
 * ZMap Copyright 2013 Regents of the University of Michigan
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 */

#include "send.h"

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>

#include "../lib/includes.h"
#include "../lib/logger.h"
#include "../lib/random.h"
#include "../lib/blocklist.h"
#include "../lib/lockfd.h"
#include "../lib/pbm.h"

#include "aesrand.h"
#include "get_gateway.h"
#include "iterator.h"
#include "probe_modules/packet.h"
#include "probe_modules/probe_modules.h"
#include "shard.h"
#include "state.h"
#include "validate.h"

// OS specific functions called by send_run
static inline int send_packet(sock_t sock, void *buf, int len, uint32_t idx);
static inline int send_run_init(sock_t sock);

// Include the right implementations
#if defined(PFRING)
#include "send-pfring.h"
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) ||     \
    defined(__DragonFly__)
#include "send-bsd.h"
#else /* LINUX */
#include "send-linux.h"
#endif /* __APPLE__ || __FreeBSD__ || __NetBSD__ || __DragonFly__ */

// The iterator over the cyclic group

// Lock for send run
static pthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER;

// Source ports for outgoing packets
static uint16_t num_src_ports;

void sig_handler_increase_speed(UNUSED int signal)
{
	int old_rate = zconf.rate;
	zconf.rate += (zconf.rate * 0.05);
	log_info("send", "send rate increased from %i to %i pps.", old_rate,
		 zconf.rate);
}

void sig_handler_decrease_speed(UNUSED int signal)
{
	int old_rate = zconf.rate;
	zconf.rate -= (zconf.rate * 0.05);
	log_info("send", "send rate decreased from %i to %i pps.", old_rate,
		 zconf.rate);
}

// global sender initialize (not thread specific)
iterator_t *send_init(void)
{
	// generate a new primitive root and starting position
	iterator_t *it;
	uint32_t num_subshards =
	    (uint32_t)zconf.senders * (uint32_t)zconf.total_shards;
	if (num_subshards > blocklist_count_allowed()) {
		log_fatal("send", "senders * shards > allowed probes");
	}
	if (zsend.max_targets && (num_subshards > zsend.max_targets)) {
		log_fatal("send", "senders * shards > max targets");
	}
	it = iterator_init(zconf.senders, zconf.shard_num, zconf.total_shards);
	// determine the source address offset from which we'll send packets
	struct in_addr temp;
	temp.s_addr = zconf.source_ip_addresses[0];
	log_debug("send", "srcip_first: %s", inet_ntoa(temp));
	temp.s_addr = zconf.source_ip_addresses[zconf.number_source_ips - 1];
	log_debug("send", "srcip_last: %s", inet_ntoa(temp));

	// process the source port range that ZMap is allowed to use
	num_src_ports = zconf.source_port_last - zconf.source_port_first + 1;
	log_debug("send", "will send from %u address%s on %hu source ports",
		  zconf.number_source_ips,
		  ((zconf.number_source_ips == 1) ? "" : "es"), num_src_ports);
	// global initialization for send module
	assert(zconf.probe_module);
	if (zconf.probe_module->global_initialize) {
		if (zconf.probe_module->global_initialize(&zconf)) {
			log_fatal(
			    "send",
			    "global initialization for probe module failed.");
		}
	}

	// only allow bandwidth or rate
	if (zconf.bandwidth > 0 && zconf.rate > 0) {
		log_fatal(
		    "send",
		    "must specify rate or bandwidth, or neither, not both.");
	}

	// Convert specified bandwidth to packet rate. This is an estimate using the
	// max packet size a probe module will generate.
	if (zconf.bandwidth > 0) {
		size_t pkt_len = zconf.probe_module->max_packet_length;
		pkt_len *= 8;
		// 7 byte MAC preamble, 1 byte Start frame, 4 byte CRC, 12 byte
		// inter-frame gap
		pkt_len += 8 * 24;
		// adjust calculated length if less than the minimum size of an
		// ethernet frame
		if (pkt_len < 84 * 8) {
			pkt_len = 84 * 8;
		}
		// rate is a uint32_t so, don't overflow
		if (zconf.bandwidth / pkt_len > 0xFFFFFFFFu) {
			zconf.rate = 0;
		} else {
			zconf.rate = zconf.bandwidth / pkt_len;
			if (zconf.rate == 0) {
				log_warn(
				    "send",
				    "bandwidth %lu bit/s is slower than 1 pkt/s, "
				    "setting rate to 1 pkt/s",
				    zconf.bandwidth);
				zconf.rate = 1;
			}
		}
		log_debug(
		    "send",
		    "using bandwidth %lu bits/s for %zu byte probe, rate set to %d pkt/s",
		    zconf.bandwidth, pkt_len / 8, zconf.rate);
	}
	// convert default placeholder to default value
	if (zconf.rate == -1) {
		// default 10K pps
		zconf.rate = 10000;
	}
	// log rate, if explicitly specified
	if (zconf.rate < 0) {
		log_fatal("send", "rate impossibly slow");
	}
	if (zconf.rate > 0 && zconf.bandwidth <= 0) {
		log_debug("send", "rate set to %d pkt/s", zconf.rate);
	}
	// Get the source hardware address, and give it to the probe
	// module
	if (!zconf.hw_mac_set) {
		if (get_iface_hw_addr(zconf.iface, zconf.hw_mac)) {
			log_fatal(
			    "send",
			    "ZMap could not retrieve the hardware (MAC) address for "
			    "the interface \"%s\". You likely do not privileges to open a raw packet socket. "
			    "Are you running as root or with the CAP_NET_RAW capability? If you are, you "
			    "may need to manually set the source MAC address with the \"--source-mac\" flag.",
			    zconf.iface);
			return NULL;
		}
		log_debug(
		    "send",
		    "no source MAC provided. "
		    "automatically detected %02x:%02x:%02x:%02x:%02x:%02x as hw "
		    "interface for %s",
		    zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2],
		    zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5],
		    zconf.iface);
	}
	log_debug("send", "source MAC address %02x:%02x:%02x:%02x:%02x:%02x",
		  zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2],
		  zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5]);

	if (zconf.dryrun) {
		log_info("send", "dryrun mode -- won't actually send packets");
	}
	// initialize random validation key
	validate_init();
	// setup signal handlers for changing scan speed
	signal(SIGUSR1, sig_handler_increase_speed);
	signal(SIGUSR2, sig_handler_decrease_speed);
	zsend.start = now();
	return it;
}

static inline ipaddr_n_t get_src_ip(ipaddr_n_t dst, int local_offset)
{
	if (zconf.number_source_ips == 1) {
		return zconf.source_ip_addresses[0];
	}
	return zconf.source_ip_addresses[(ntohl(dst) + local_offset) %
					 zconf.number_source_ips];
}

// one sender thread
int send_run(sock_t st, shard_t *s)
{
	log_debug("send", "send thread started");
	pthread_mutex_lock(&send_mutex);
	// Allocate a buffer to hold the outgoing packet
	char buf[MAX_PACKET_SIZE];
	memset(buf, 0, MAX_PACKET_SIZE);

	// OS specific per-thread init
	if (send_run_init(st)) {<commit_msg>STM: Add missing unlock on error case in send.c<commit_after>/*
 * ZMap Copyright 2013 Regents of the University of Michigan
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 */

#include "send.h"

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>

#include "../lib/includes.h"
#include "../lib/logger.h"
#include "../lib/random.h"
#include "../lib/blocklist.h"
#include "../lib/lockfd.h"
#include "../lib/pbm.h"

#include "aesrand.h"
#include "get_gateway.h"
#include "iterator.h"
#include "probe_modules/packet.h"
#include "probe_modules/probe_modules.h"
#include "shard.h"
#include "state.h"
#include "validate.h"

// OS specific functions called by send_run
static inline int send_packet(sock_t sock, void *buf, int len, uint32_t idx);
static inline int send_run_init(sock_t sock);

// Include the right implementations
#if defined(PFRING)
#include "send-pfring.h"
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) ||     \
    defined(__DragonFly__)
#include "send-bsd.h"
#else /* LINUX */
#include "send-linux.h"
#endif /* __APPLE__ || __FreeBSD__ || __NetBSD__ || __DragonFly__ */

// The iterator over the cyclic group

// Lock for send run
static pthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER;

// Source ports for outgoing packets
static uint16_t num_src_ports;

void sig_handler_increase_speed(UNUSED int signal)
{
	int old_rate = zconf.rate;
	zconf.rate += (zconf.rate * 0.05);
	log_info("send", "send rate increased from %i to %i pps.", old_rate,
		 zconf.rate);
}

void sig_handler_decrease_speed(UNUSED int signal)
{
	int old_rate = zconf.rate;
	zconf.rate -= (zconf.rate * 0.05);
	log_info("send", "send rate decreased from %i to %i pps.", old_rate,
		 zconf.rate);
}

// global sender initialize (not thread specific)
iterator_t *send_init(void)
{
	// generate a new primitive root and starting position
	iterator_t *it;
	uint32_t num_subshards =
	    (uint32_t)zconf.senders * (uint32_t)zconf.total_shards;
	if (num_subshards > blocklist_count_allowed()) {
		log_fatal("send", "senders * shards > allowed probes");
	}
	if (zsend.max_targets && (num_subshards > zsend.max_targets)) {
		log_fatal("send", "senders * shards > max targets");
	}
	it = iterator_init(zconf.senders, zconf.shard_num, zconf.total_shards);
	// determine the source address offset from which we'll send packets
	struct in_addr temp;
	temp.s_addr = zconf.source_ip_addresses[0];
	log_debug("send", "srcip_first: %s", inet_ntoa(temp));
	temp.s_addr = zconf.source_ip_addresses[zconf.number_source_ips - 1];
	log_debug("send", "srcip_last: %s", inet_ntoa(temp));

	// process the source port range that ZMap is allowed to use
	num_src_ports = zconf.source_port_last - zconf.source_port_first + 1;
	log_debug("send", "will send from %u address%s on %hu source ports",
		  zconf.number_source_ips,
		  ((zconf.number_source_ips == 1) ? "" : "es"), num_src_ports);
	// global initialization for send module
	assert(zconf.probe_module);
	if (zconf.probe_module->global_initialize) {
		if (zconf.probe_module->global_initialize(&zconf)) {
			log_fatal(
			    "send",
			    "global initialization for probe module failed.");
		}
	}

	// only allow bandwidth or rate
	if (zconf.bandwidth > 0 && zconf.rate > 0) {
		log_fatal(
		    "send",
		    "must specify rate or bandwidth, or neither, not both.");
	}

	// Convert specified bandwidth to packet rate. This is an estimate using the
	// max packet size a probe module will generate.
	if (zconf.bandwidth > 0) {
		size_t pkt_len = zconf.probe_module->max_packet_length;
		pkt_len *= 8;
		// 7 byte MAC preamble, 1 byte Start frame, 4 byte CRC, 12 byte
		// inter-frame gap
		pkt_len += 8 * 24;
		// adjust calculated length if less than the minimum size of an
		// ethernet frame
		if (pkt_len < 84 * 8) {
			pkt_len = 84 * 8;
		}
		// rate is a uint32_t so, don't overflow
		if (zconf.bandwidth / pkt_len > 0xFFFFFFFFu) {
			zconf.rate = 0;
		} else {
			zconf.rate = zconf.bandwidth / pkt_len;
			if (zconf.rate == 0) {
				log_warn(
				    "send",
				    "bandwidth %lu bit/s is slower than 1 pkt/s, "
				    "setting rate to 1 pkt/s",
				    zconf.bandwidth);
				zconf.rate = 1;
			}
		}
		log_debug(
		    "send",
		    "using bandwidth %lu bits/s for %zu byte probe, rate set to %d pkt/s",
		    zconf.bandwidth, pkt_len / 8, zconf.rate);
	}
	// convert default placeholder to default value
	if (zconf.rate == -1) {
		// default 10K pps
		zconf.rate = 10000;
	}
	// log rate, if explicitly specified
	if (zconf.rate < 0) {
		log_fatal("send", "rate impossibly slow");
	}
	if (zconf.rate > 0 && zconf.bandwidth <= 0) {
		log_debug("send", "rate set to %d pkt/s", zconf.rate);
	}
	// Get the source hardware address, and give it to the probe
	// module
	if (!zconf.hw_mac_set) {
		if (get_iface_hw_addr(zconf.iface, zconf.hw_mac)) {
			log_fatal(
			    "send",
			    "ZMap could not retrieve the hardware (MAC) address for "
			    "the interface \"%s\". You likely do not privileges to open a raw packet socket. "
			    "Are you running as root or with the CAP_NET_RAW capability? If you are, you "
			    "may need to manually set the source MAC address with the \"--source-mac\" flag.",
			    zconf.iface);
			return NULL;
		}
		log_debug(
		    "send",
		    "no source MAC provided. "
		    "automatically detected %02x:%02x:%02x:%02x:%02x:%02x as hw "
		    "interface for %s",
		    zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2],
		    zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5],
		    zconf.iface);
	}
	log_debug("send", "source MAC address %02x:%02x:%02x:%02x:%02x:%02x",
		  zconf.hw_mac[0], zconf.hw_mac[1], zconf.hw_mac[2],
		  zconf.hw_mac[3], zconf.hw_mac[4], zconf.hw_mac[5]);

	if (zconf.dryrun) {
		log_info("send", "dryrun mode -- won't actually send packets");
	}
	// initialize random validation key
	validate_init();
	// setup signal handlers for changing scan speed
	signal(SIGUSR1, sig_handler_increase_speed);
	signal(SIGUSR2, sig_handler_decrease_speed);
	zsend.start = now();
	return it;
}

static inline ipaddr_n_t get_src_ip(ipaddr_n_t dst, int local_offset)
{
	if (zconf.number_source_ips == 1) {
		return zconf.source_ip_addresses[0];
	}
	return zconf.source_ip_addresses[(ntohl(dst) + local_offset) %
					 zconf.number_source_ips];
}

// one sender thread
int send_run(sock_t st, shard_t *s)
{
	log_debug("send", "send thread started");
	pthread_mutex_lock(&send_mutex);
	// Allocate a buffer to hold the outgoing packet
	char buf[MAX_PACKET_SIZE];
	memset(buf, 0, MAX_PACKET_SIZE);

	// OS specific per-thread init
	if (send_run_init(st)) {
		pthread_mutex_unlock(&send_mutex);
{'fraction_non_alphanumeric': 0.1327234444202425, 'fraction_numerical': 0.015537646119218762, 'mean_word_length': 3.7252144082332763, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 47, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, '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': '1291572', 'n_tokens_mistral': 5424, 'n_tokens_neox': 4964, 'n_words': 1371}