예제 #1
0
/* cf_fault_sink_hold
 * Register but don't activate a sink for faults - return sink object pointer on
 * success, NULL on failure. Only use at startup when parsing config file. After
 * all sinks are registered, activate via cf_fault_sink_activate_all_held(). */
cf_fault_sink *
cf_fault_sink_hold(char *path)
{
	if (num_held_fault_sinks >= CF_FAULT_SINKS_MAX) {
		cf_warning(CF_MISC, "too many fault sinks");
		return NULL;
	}

	cf_fault_sink *s = &cf_fault_sinks[num_held_fault_sinks];

	s->path = cf_strdup(path);

	if (! s->path) {
		cf_warning(CF_MISC, "failed allocation for sink path");
		return NULL;
	}

	// If a context is not added, its runtime default will be CF_INFO.
	for (int i = 0; i < CF_FAULT_CONTEXT_UNDEF; i++) {
		s->limit[i] = CF_INFO;
	}

	num_held_fault_sinks++;

	return s;
}
void cloneIC(icol_t *dic, icol_t *sic)
{
	bzero(dic, sizeof(icol_t));
	dic->cmatch = sic->cmatch;
	dic->nlo    = sic->nlo;
	//printf("cloneIC: cmatch: %d nlo: %d\n", dic->cmatch, dic->nlo);
	if (dic->nlo) {
		dic->lo = cf_malloc(sizeof(char *) * dic->nlo);
		for (uint32 j = 0; j < dic->nlo; j++) {
			dic->lo[j] = cf_strdup(sic->lo[j]);
		}
	}
}
예제 #3
0
int
cf_ipaddr_get(int socket, char *nic_id, char **node_ip )
{
	struct sockaddr_in sin;
	struct ifreq ifr;
	in_addr_t ip_addr;

	memset(&ip_addr, 0, sizeof(in_addr_t));
	memset(&sin, 0, sizeof(struct sockaddr));
	memset(&ifr, 0, sizeof(ifr));

	// copy the nic name (eth0, eth1, eth2, etc.) ifr variable structure
	strncpy(ifr.ifr_name, nic_id, IFNAMSIZ);

	// get the ifindex for the adapter...
	if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
		cf_debug(CF_MISC, "Can't get ifindex for adapter %s - %d %s\n", nic_id, errno, cf_strerror(errno));
		return(-1);
	}

	// get the IP address
	memset(&sin, 0, sizeof(struct sockaddr));
	memset(&ifr, 0, sizeof(ifr));
	strncpy(ifr.ifr_name, nic_id, IFNAMSIZ);
	ifr.ifr_addr.sa_family = AF_INET;
	if (ioctl(socket, SIOCGIFADDR, &ifr)< 0) {
		cf_debug(CF_MISC, "can't get IP address: %d %s", errno, cf_strerror(errno));
		return(-1);
	}
	memcpy(&sin, &ifr.ifr_addr, sizeof(struct sockaddr));
	ip_addr = sin.sin_addr.s_addr;
	char cpaddr[24];
	if (NULL == inet_ntop(AF_INET, &ip_addr, (char *)cpaddr, sizeof(cpaddr))) {
		cf_warning(CF_MISC, "received suspicious address %s : %s", cpaddr, cf_strerror(errno));
		return(-1);
	}
	cf_info (CF_MISC, "Node ip: %s", cpaddr);
	*node_ip = cf_strdup(cpaddr);

	return(0);
}
예제 #4
0
/* cf_fault_sink_add
 * Register an sink for faults */
cf_fault_sink *
cf_fault_sink_add(char *path)
{
	cf_fault_sink *s;

	if ((CF_FAULT_SINKS_MAX - 1) == cf_fault_sinks_inuse)
		return(NULL);

	s = &cf_fault_sinks[cf_fault_sinks_inuse++];
	s->path = cf_strdup(path);
	if (0 == strncmp(path, "stderr", 6))
		s->fd = 2;
	else {
		if (-1 == (s->fd = open(path, SINK_OPEN_FLAGS, SINK_OPEN_MODE))) {
			cf_fault_sinks_inuse--;
			return(NULL);
		}
	}

	for (int i = 0; i < CF_FAULT_CONTEXT_UNDEF; i++)
		s->limit[i] = CF_INFO;

	return(s);
}
예제 #5
0
/* cf_fault_sink_add
 * Register an sink for faults */
cf_fault_sink *
cf_fault_sink_add(char *path)
{
	cf_fault_sink *s;

	if ((CF_FAULT_SINKS_MAX - 1) == cf_fault_sinks_inuse)
		return(NULL);

	s = &cf_fault_sinks[cf_fault_sinks_inuse++];
	s->path = cf_strdup(path);
	if (0 == strncmp(path, "stderr", 6))
		s->fd = 2;
	else {
		if (-1 == (s->fd = open(path, O_WRONLY|O_CREAT|O_APPEND|O_NONBLOCK, S_IRUSR|S_IWUSR))) {
			cf_fault_sinks_inuse--;
			return(NULL);
		}
	}

	for (int i = 0; i < CF_FAULT_CONTEXT_UNDEF; i++)
		s->limit[i] = CF_INFO;

	return(s);
}
예제 #6
0
int
main(int argc, char **argv)
{
	g_start_sec = cf_get_seconds();

	// Initialize cf_thread wrapper.
	cf_thread_init();

	// Initialize memory allocation.
	cf_alloc_init();

	// Initialize fault management framework.
	cf_fault_init();

	// Setup signal handlers.
	as_signal_setup();

	// Initialize TLS library.
	tls_check_init();

	int opt;
	int opt_i;
	const char *config_file = DEFAULT_CONFIG_FILE;
	bool run_in_foreground = false;
	bool new_style_daemon = false;
	bool cold_start_cmd = false;
	uint32_t instance = 0;

	// Parse command line options.
	while ((opt = getopt_long(argc, argv, "", CMD_OPTS, &opt_i)) != -1) {
		switch (opt) {
		case 'h':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s\n", HELP);
			return 0;
		case 'v':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s build %s\n", aerospike_build_type, aerospike_build_id);
			return 0;
		case 'f':
			config_file = cf_strdup(optarg);
			break;
		case 'F':
			// As a "new-style" daemon(*), asd runs in the foreground and
			// ignores the following configuration items:
			//  - user ('user')
			//	- group ('group')
			//  - PID file ('pidfile')
			//
			// If ignoring configuration items, or if the 'console' sink is not
			// specified, warnings will appear in stderr.
			//
			// (*) http://0pointer.de/public/systemd-man/daemon.html#New-Style%20Daemons
			run_in_foreground = true;
			new_style_daemon = true;
			break;
		case 'd':
			run_in_foreground = true;
			break;
		case 'c':
			cold_start_cmd = true;
			break;
		case 'n':
			instance = (uint32_t)strtol(optarg, NULL, 0);
			break;
		default:
			// fprintf() since we don't want cf_fault's prefix.
			fprintf(stderr, "%s\n", USAGE);
			return 1;
		}
	}

	// Set all fields in the global runtime configuration instance. This parses
	// the configuration file, and creates as_namespace objects. (Return value
	// is a shortcut pointer to the global runtime configuration instance.)
	as_config *c = as_config_init(config_file);

	// Detect NUMA topology and, if requested, prepare for CPU and NUMA pinning.
	cf_topo_config(c->auto_pin, (cf_topo_numa_node_index)instance,
			&c->service.bind);

	// Perform privilege separation as necessary. If configured user & group
	// don't have root privileges, all resources created or reopened past this
	// point must be set up so that they are accessible without root privileges.
	// If not, the process will self-terminate with (hopefully!) a log message
	// indicating which resource is not set up properly.
	cf_process_privsep(c->uid, c->gid);

	//
	// All resources such as files, devices, and shared memory must be created
	// or reopened below this line! (The configuration file is the only thing
	// that must be opened above, in order to parse the user & group.)
	//==========================================================================

	// A "new-style" daemon expects console logging to be configured. (If not,
	// log messages won't be seen via the standard path.)
	if (new_style_daemon) {
		if (! cf_fault_console_is_held()) {
			cf_warning(AS_AS, "in new-style daemon mode, console logging is not configured");
		}
	}

	// Activate log sinks. Up to this point, 'cf_' log output goes to stderr,
	// filtered according to NO_SINKS_LIMIT in fault.c. After this point, 'cf_'
	// log output will appear in all log file sinks specified in configuration,
	// with specified filtering. If console sink is specified in configuration,
	// 'cf_' log output will continue going to stderr, but filtering will switch
	// from NO_SINKS_LIMIT to that specified in console sink configuration.
	if (0 != cf_fault_sink_activate_all_held()) {
		// Specifics of failure are logged in cf_fault_sink_activate_all_held().
		cf_crash_nostack(AS_AS, "can't open log sink(s)");
	}

	// Daemonize asd if specified. After daemonization, output to stderr will no
	// longer appear in terminal. Instead, check /tmp/aerospike-console.<pid>
	// for console output.
	if (! run_in_foreground && c->run_as_daemon) {
		// Don't close any open files when daemonizing. At this point only log
		// sink files are open - instruct cf_process_daemonize() to ignore them.
		int open_fds[CF_FAULT_SINKS_MAX];
		int num_open_fds = cf_fault_sink_get_fd_list(open_fds);

		cf_process_daemonize(open_fds, num_open_fds);
	}

	// Log which build this is - should be the first line in the log file.
	cf_info(AS_AS, "<><><><><><><><><><>  %s build %s  <><><><><><><><><><>",
			aerospike_build_type, aerospike_build_id);

	// Includes echoing the configuration file to log.
	as_config_post_process(c, config_file);

	xdr_config_post_process();

	// If we allocated a non-default config file name, free it.
	if (config_file != DEFAULT_CONFIG_FILE) {
		cf_free((void*)config_file);
	}

	// Write the pid file, if specified.
	if (! new_style_daemon) {
		write_pidfile(c->pidfile);
	}
	else {
		if (c->pidfile) {
			cf_warning(AS_AS, "will not write PID file in new-style daemon mode");
		}
	}

	// Check that required directories are set up properly.
	validate_directory(c->work_directory, "work");
	validate_directory(c->mod_lua.user_path, "Lua user");
	validate_smd_directory();

	// Initialize subsystems. At this point we're allocating local resources,
	// starting worker threads, etc. (But no communication with other server
	// nodes or clients yet.)

	as_json_init();				// Jansson JSON API used by System Metadata
	as_index_tree_gc_init();	// thread to purge dropped index trees
	as_sindex_thr_init();		// defrag secondary index (ok during population)
	as_nsup_init();				// load previous evict-void-time(s)

	// Initialize namespaces. Each namespace decides here whether it will do a
	// warm or cold start. Index arenas, partition structures and index tree
	// structures are initialized. Secondary index system metadata is restored.
	as_namespaces_init(cold_start_cmd, instance);

	// Initialize the storage system. For warm and cool restarts, this includes
	// fully resuming persisted indexes - this may take a few minutes.
	as_storage_init();

	// Migrate memory to correct NUMA node (includes resumed index arenas).
	cf_topo_migrate_memory();

	// Drop capabilities that we kept only for initialization.
	cf_process_drop_startup_caps();

	// Activate the storage system. For cold starts and cool restarts, this
	// includes full drive scans - this may take several hours. The defrag
	// subsystem starts operating at the end of this call.
	as_storage_load();

	// Populate all secondary indexes. This may block for a long time.
	as_sindex_boot_populateall();

	cf_info(AS_AS, "initializing services...");

	cf_dns_init();				// DNS resolver
	as_netio_init();			// query responses
	as_security_init();			// security features
	as_tsvc_init();				// all transaction handling
	as_hb_init();				// inter-node heartbeat
	as_skew_monitor_init();		// clock skew monitor
	as_fabric_init();			// inter-node communications
	as_exchange_init();			// initialize the cluster exchange subsystem
	as_clustering_init();		// clustering-v5 start
	as_info_init();				// info transaction handling
	as_migrate_init();			// move data between nodes
	as_proxy_init();			// do work on behalf of others
	as_rw_init();				// read & write service
	as_query_init();			// query transaction handling
	as_udf_init();				// user-defined functions
	as_scan_init();				// scan a namespace or set
	as_batch_init();			// batch transaction handling
	as_xdr_init();				// cross data-center replication
	as_mon_init();				// monitor

	// Wait for enough available storage. We've been defragging all along, but
	// here we wait until it's enough. This may block for a long time.
	as_storage_wait_for_defrag();

	// Start subsystems. At this point we may begin communicating with other
	// cluster nodes, and ultimately with clients.

	as_smd_start();				// enables receiving cluster state change events
	as_health_start();			// starts before fabric and hb to capture them
	as_fabric_start();			// may send & receive fabric messages
	as_xdr_start();				// XDR should start before it joins other nodes
	as_hb_start();				// start inter-node heartbeat
	as_exchange_start();		// start the cluster exchange subsystem
	as_clustering_start();		// clustering-v5 start
	as_nsup_start();			// may send evict-void-time(s) to other nodes
	as_service_start();			// server will now receive client transactions
	as_info_port_start();		// server will now receive info transactions
	as_ticker_start();			// only after everything else is started

	// Relevant for enterprise edition only.
	as_storage_start_tomb_raider();

	// Log a service-ready message.
	cf_info(AS_AS, "service ready: soon there will be cake!");

	//--------------------------------------------
	// Startup is done. This thread will now wait
	// quietly for a shutdown signal.
	//

	// Stop this thread from finishing. Intentionally deadlocking on a mutex is
	// a remarkably efficient way to do this.
	pthread_mutex_lock(&g_main_deadlock);
	g_startup_complete = true;
	pthread_mutex_lock(&g_main_deadlock);

	// When the service is running, you are here (deadlocked) - the signals that
	// stop the service (yes, these signals always occur in this thread) will
	// unlock the mutex, allowing us to continue.

	g_shutdown_started = true;
	pthread_mutex_unlock(&g_main_deadlock);
	pthread_mutex_destroy(&g_main_deadlock);

	//--------------------------------------------
	// Received a shutdown signal.
	//

	as_storage_shutdown(instance);
	as_xdr_shutdown();

	cf_info(AS_AS, "finished clean shutdown - exiting");

	// If shutdown was totally clean (all threads joined) we could just return,
	// but for now we exit to make sure all threads die.
#ifdef DOPROFILE
	exit(0); // exit(0) so profile build actually dumps gmon.out
#else
	_exit(0);
#endif

	return 0;
}
예제 #7
0
as_geojson *as_geojson_new_strdup(const char * s)
{
	return as_geojson_new(cf_strdup(s), true);
}
예제 #8
0
int
main(int argc, char **argv)
{
#ifdef USE_ASM
	as_mallocation_t asm_array[MAX_NUM_MALLOCATIONS];

	// Zero-out the statically-allocated array of memory allocation locations.
	memset(asm_array, 0, sizeof(asm_array));

	// Set the ASMalloc callback user data.
	g_my_cb_udata = asm_array;

	// This must come first to allow initialization of the ASMalloc library.
	asm_init();
#endif // defined(USE_ASM)

#ifdef USE_JEM
	// Initialize the JEMalloc interface.
	jem_init(true);
#endif

	// Initialize ref-counting system.
	cf_rc_init(NULL);

	// Initialize fault management framework.
	cf_fault_init();

	// Setup signal handlers.
	as_signal_setup();

	// Initialize the Jansson JSON API.
	as_json_init();

	int i;
	int cmd_optidx;
	const char *config_file = DEFAULT_CONFIG_FILE;
	bool run_in_foreground = false;
	bool cold_start_cmd = false;
	uint32_t instance = 0;

	// Parse command line options.
	while (-1 != (i = getopt_long(argc, argv, "", cmd_opts, &cmd_optidx))) {
		switch (i) {
		case 'h':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s\n", HELP);
			return 0;
		case 'v':
			// printf() since we want stdout and don't want cf_fault's prefix.
			printf("%s build %s\n", aerospike_build_type, aerospike_build_id);
			return 0;
		case 'f':
			config_file = cf_strdup(optarg);
			cf_assert(config_file, AS_AS, CF_CRITICAL, "config filename cf_strdup failed");
			break;
		case 'd':
			run_in_foreground = true;
			break;
		case 'c':
			cold_start_cmd = true;
			break;
		case 'n':
			instance = (uint32_t)strtol(optarg, NULL, 0);
			break;
		default:
			// fprintf() since we don't want cf_fault's prefix.
			fprintf(stderr, "%s\n", USAGE);
			return 1;
		}
	}

	// Set all fields in the global runtime configuration instance. This parses
	// the configuration file, and creates as_namespace objects. (Return value
	// is a shortcut pointer to the global runtime configuration instance.)
	as_config *c = as_config_init(config_file);

#ifdef USE_ASM
	g_asm_hook_enabled = g_asm_cb_enabled = c->asmalloc_enabled;

	long initial_tid = syscall(SYS_gettid);
#endif

#ifdef MEM_COUNT
	// [Note: This should ideally be at the very start of the "main()" function,
	//        but we need to wait until after the config file has been parsed in
	//        order to support run-time configurability.]
	mem_count_init(c->memory_accounting ? MEM_COUNT_ENABLE : MEM_COUNT_DISABLE);
#endif

	// Perform privilege separation as necessary. If configured user & group
	// don't have root privileges, all resources created or reopened past this
	// point must be set up so that they are accessible without root privileges.
	// If not, the process will self-terminate with (hopefully!) a log message
	// indicating which resource is not set up properly.
	if (0 != c->uid && 0 == geteuid()) {
		// To see this log, change NO_SINKS_LIMIT in fault.c:
		cf_info(AS_AS, "privsep to %d %d", c->uid, c->gid);
		cf_process_privsep(c->uid, c->gid);
	}

	//
	// All resources such as files, devices, and shared memory must be created
	// or reopened below this line! (The configuration file is the only thing
	// that must be opened above, in order to parse the user & group.)
	//==========================================================================

	// Activate log sinks. Up to this point, 'cf_' log output goes to stderr,
	// filtered according to NO_SINKS_LIMIT in fault.c. After this point, 'cf_'
	// log output will appear in all log file sinks specified in configuration,
	// with specified filtering. If console sink is specified in configuration,
	// 'cf_' log output will continue going to stderr, but filtering will switch
	// from NO_SINKS_LIMIT to that specified in console sink configuration.
	if (0 != cf_fault_sink_activate_all_held()) {
		// Specifics of failure are logged in cf_fault_sink_activate_all_held().
		cf_crash_nostack(AS_AS, "can't open log sink(s)");
	}

	// Daemonize asd if specified. After daemonization, output to stderr will no
	// longer appear in terminal. Instead, check /tmp/aerospike-console.<pid>
	// for console output.
	if (! run_in_foreground && c->run_as_daemon) {
		// Don't close any open files when daemonizing. At this point only log
		// sink files are open - instruct cf_process_daemonize() to ignore them.
		int open_fds[CF_FAULT_SINKS_MAX];
		int num_open_fds = cf_fault_sink_get_fd_list(open_fds);

		cf_process_daemonize(open_fds, num_open_fds);
	}

#ifdef USE_ASM
	// Log the main thread's Linux Task ID (pre- and post-fork) to the console.
	fprintf(stderr, "Initial main thread tid: %lu\n", initial_tid);

	if (! run_in_foreground && c->run_as_daemon) {
		fprintf(stderr, "Post-daemonize main thread tid: %lu\n",
				syscall(SYS_gettid));
	}
#endif

	// Log which build this is - should be the first line in the log file.
	cf_info(AS_AS, "<><><><><><><><><><>  %s build %s  <><><><><><><><><><>",
			aerospike_build_type, aerospike_build_id);

	// Includes echoing the configuration file to log.
	as_config_post_process(c, config_file);

	// If we allocated a non-default config file name, free it.
	if (config_file != DEFAULT_CONFIG_FILE) {
		cf_free((void*)config_file);
	}

	// Write the pid file, if specified.
	write_pidfile(c->pidfile);

	// Check that required directories are set up properly.
	validate_directory(c->work_directory, "work");
	validate_directory(c->mod_lua.system_path, "Lua system");
	validate_directory(c->mod_lua.user_path, "Lua user");
	validate_smd_directory();

	// Initialize subsystems. At this point we're allocating local resources,
	// starting worker threads, etc. (But no communication with other server
	// nodes or clients yet.)

	as_smd_init();				// System Metadata first - others depend on it
	ai_init();					// before as_storage_init() populates indexes
	as_sindex_thr_init();		// defrag secondary index (ok during population)

	// Initialize namespaces. Each namespace decides here whether it will do a
	// warm or cold start. Index arenas, partition structures and index tree
	// structures are initialized. Secondary index system metadata is restored.
	as_namespaces_init(cold_start_cmd, instance);

	// Initialize the storage system. For cold starts, this includes reading
	// all the objects off the drives. This may block for a long time. The
	// defrag subsystem starts operating at the end of this call.
	as_storage_init();

	// Populate all secondary indexes. This may block for a long time.
	as_sindex_boot_populateall();

	cf_info(AS_AS, "initializing services...");

	as_netio_init();
	as_security_init();			// security features
	as_tsvc_init();				// all transaction handling
	as_hb_init();				// inter-node heartbeat
	as_fabric_init();			// inter-node communications
	as_info_init();				// info transaction handling
	as_paxos_init();			// cluster consensus algorithm
	as_migrate_init();			// move data between nodes
	as_proxy_init();			// do work on behalf of others
	as_write_init();			// write service
	as_query_init();			// query transaction handling
	as_udf_init();				// apply user-defined functions
	as_scan_init();				// scan a namespace or set
	as_batch_init();			// batch transaction handling
	as_batch_direct_init();		// low priority transaction handling        
	as_xdr_init();				// cross data-center replication
	as_mon_init();				// monitor

	// Wait for enough available storage. We've been defragging all along, but
	// here we wait until it's enough. This may block for a long time.
	as_storage_wait_for_defrag();

	// Start subsystems. At this point we may begin communicating with other
	// cluster nodes, and ultimately with clients.

	as_smd_start(c->smd);		// enables receiving paxos state change events
	as_fabric_start();			// may send & receive fabric messages
	as_hb_start();				// start inter-node heatbeat
	as_paxos_start();			// blocks until cluster membership is obtained
	as_nsup_start();			// may send delete transactions to other nodes
	as_demarshal_start();		// server will now receive client transactions
	as_info_port_start();		// server will now receive info transactions
	info_debug_ticker_start();	// only after everything else is started

	// Log a service-ready message.
	cf_info(AS_AS, "service ready: soon there will be cake!");

	//--------------------------------------------
	// Startup is done. This thread will now wait
	// quietly for a shutdown signal.
	//

	// Stop this thread from finishing. Intentionally deadlocking on a mutex is
	// a remarkably efficient way to do this.
	pthread_mutex_init(&g_NONSTOP, NULL);
	pthread_mutex_lock(&g_NONSTOP);
	g_startup_complete = true;
	pthread_mutex_lock(&g_NONSTOP);

	// When the service is running, you are here (deadlocked) - the signals that
	// stop the service (yes, these signals always occur in this thread) will
	// unlock the mutex, allowing us to continue.

	g_shutdown_started = true;
	pthread_mutex_unlock(&g_NONSTOP);
	pthread_mutex_destroy(&g_NONSTOP);

	//--------------------------------------------
	// Received a shutdown signal.
	//

	as_storage_shutdown();
	as_xdr_shutdown();
	as_smd_shutdown(c->smd);

	cf_info(AS_AS, "finished clean shutdown - exiting");

	// If shutdown was totally clean (all threads joined) we could just return,
	// but for now we exit to make sure all threads die.
#ifdef DOPROFILE
	exit(0); // exit(0) so profile build actually dumps gmon.out
#else
	_exit(0);
#endif

	return 0;
}
예제 #9
0
static void* cert_blacklist_read(const char * path)
{
	FILE* fp = fopen(path, "r");
	if (fp == NULL) {
		as_log_warn("Failed to open cert blacklist '%s': %s",
					path, strerror(errno));
		return NULL;
	}

	size_t capacity = 32;
	size_t sz = sizeof(cert_blacklist) + (capacity * sizeof(cert_spec));
	cert_blacklist* cbp = cf_malloc(sz);
	cbp->ncerts = 0;

	char buffer[1024];
	while (true) {
		char* line = fgets(buffer, sizeof(buffer), fp);
		if (! line) {
			break;
		}

		// Lines begining with a '#' are comments.
		if (line[0] == '#') {
			continue;
		}
		
		char* saveptr = NULL;
		char* hex_serial = strtok_r(line, " \t\r\n", &saveptr);
		if (! hex_serial) {
			continue;
		}

		// Skip all additional whitespace.
		while (isspace(*saveptr)) {
			++saveptr;
		}

		// Everything to the end of the line is issuer name.  Note we
		// do not consider whitespace a separator anymore.
		char* issuer_name = strtok_r(NULL, "\r\n", &saveptr);

		// Do we need more room?
		if (cbp->ncerts == capacity) {
			capacity *= 2;
			size_t sz = sizeof(cert_blacklist) + (capacity * sizeof(cert_spec));
			cbp = cf_realloc(cbp, sz);
		}

		cbp->certs[cbp->ncerts].hex_serial = cf_strdup(hex_serial);
		cbp->certs[cbp->ncerts].issuer_name =
			issuer_name ? cf_strdup(issuer_name) : NULL;

		cbp->ncerts++;
	}

	qsort(cbp->certs, cbp->ncerts, sizeof(cert_spec), cert_spec_compare);

	fclose(fp);
	
	return cbp;
}
예제 #10
0
int
cf_nodeid_get( unsigned short port, cf_node *id, char **node_ipp, hb_mode_enum hb_mode, char **hb_addrp, char **config_interface_names)
{
	int fdesc;
	struct ifreq req;

	// The default interface names can be overridden by the interface name passed into config
	char **interface_names = default_interface_names;
	bool default_config = true;
	int jlimit = 11;

	if (config_interface_names) {
		interface_names = config_interface_names;
		default_config = false;
		jlimit = 1;
	}

	if (0 >= (fdesc = socket(AF_INET, SOCK_STREAM, 0))) {
		cf_warning(CF_MISC, "can't open socket: %d %s", errno, cf_strerror(errno));
		return(-1);
	}
	int i = 0;
	bool done = false;

	while ((interface_names[i]) && (!done)) {

		int j=0;
		while ((!done) && (j < jlimit)) {

			if (default_config)
				sprintf(req.ifr_name, interface_names[i],j);
			else
				sprintf(req.ifr_name, interface_names[i]);

			if (0 == ioctl(fdesc, SIOCGIFHWADDR, &req)) {
				if (cf_ipaddr_get(fdesc, req.ifr_name, node_ipp) == 0) {
					done = true;
					break;
				}
			}

			cf_debug(CF_MISC, "can't get physical address of interface %s: %d %s", req.ifr_name, errno, cf_strerror(errno));

			j++;

		}
		i++;
	}

	if (!done) {
		if (default_config) {
			
			struct ifaddrs* interface_addrs = NULL;
			if (getifaddrs(&interface_addrs) == -1) {
				cf_warning(CF_MISC, "getifaddrs failed %d %s", errno, cf_strerror(errno));
				return -1;
			}
			if (!interface_addrs) {
				cf_warning(CF_MISC, "getifaddrs returned NULL");
				return -1;
			}

			struct ifaddrs *ifa;
			for (ifa = interface_addrs; ifa != NULL && (!done); ifa = ifa->ifa_next) {
				if (ifa->ifa_data != 0) {
					struct ifreq req;
					strcpy(req.ifr_name, ifa->ifa_name);
			
					/* Get MAC address */
					if (ioctl(fdesc, SIOCGIFHWADDR, &req) == 0) {

						uint8_t* mac = (uint8_t*)req.ifr_ifru.ifru_hwaddr.sa_data;
						/* MAC address sanity check */
						if ((mac[0] == 0 && mac[1] == 0 && mac[2] == 0 
						&& mac[3] == 0 && mac[4] == 0 && mac[5] == 0)
						|| (mac[0] == 0xff && mac[1] == 0xff && mac[2] == 0xff
						&& mac[3] == 0xff && mac[4] == 0xff && mac[5] == 0xff )) {
							
							continue;
						}
						/* Get IP address */
						if (cf_ipaddr_get(fdesc, req.ifr_name, node_ipp) == 0) {
							done = true;
							continue;
						}
					}
					else {
						/* Continue to the next interface if cannot get MAC address */
						continue;
					}
				}
			}
		}
		else {
			cf_warning(CF_MISC, "can't get physical address of interface name specfied in config file, tried %s. fatal: %d %s", interface_names[0], errno, cf_strerror(errno));
			close(fdesc);
			return(-1);
		}
	}
	if (!done) {
		cf_warning(CF_MISC, "Tried eth,bond,wlan and list of all available interfaces on device.Failed to retrieve physical address with errno %d %s\n", errno, cf_strerror(errno));
		close(fdesc);
		return(-1);
	}

	close(fdesc);
	/*
	 * Set the hb_addr to be the same as the ip address if the mode is mesh and the hb_addr parameter is empty
	 * Configuration file overrides the automatic node ip detection
	 *	- this gives us a work around in case the node ip is somehow detected wrong in production
	 */
	if (hb_mode == AS_HB_MODE_MESH)
	{
		if (*hb_addrp == NULL)
			*hb_addrp = cf_strdup(*node_ipp);

		cf_info(CF_MISC, "Heartbeat address for mesh: %s", *hb_addrp);
	}

	*id = 0;
	memcpy(id, req.ifr_hwaddr.sa_data, 6);

	memcpy(((byte *)id) + 6, &port, 2);

	cf_debug(CF_MISC, "port %d id %"PRIx64, port, *id);

	return(0);
}
예제 #11
0
char *
as_cmp_wildcard_val_tostring(const as_val *v)
{
	return cf_strdup("*");
}
예제 #12
0
char *
as_cmp_inf_val_tostring(const as_val *v)
{
	return cf_strdup("INF");
}
예제 #13
0
as_string *as_string_new_strdup(const char * s)
{
	return as_string_new(cf_strdup(s), true);
}
예제 #14
0
/*
 * Gets a unique id for this process instance
 * Uses the mac address right now
 * And combine with the unique port number, which is why it needs to be passed in
 * Needs to be a little more subtle:
 * Should stash the mac address or something, in case you have to replace a card.
 *
 * parameters-
 * Input params:
 * port - used in setting Node ID
 * hb_mode - Controls whether hb_addrp is filled out with the IP address.
 * config_interface_names - Pointer to an array of interface names if specified in the config file,
 *			    NULL if absent.
 *
 * Output params:
 * id - Node ID (address and port)
 * node_ipp - Pointer wherein the IP address is stored
 * hb_addrp - Pointer to a string wherein the heartbeat address is stored, as specified by hb_mode
 */
int
cf_nodeid_get(unsigned short port, cf_node *id, char **node_ipp, hb_mode_enum hb_mode, char **hb_addrp, const char **config_interface_names)
{
	// The default interface names can be overridden by the interface name passed into config
	const char **interface_names = default_interface_names;
	bool default_config = true;
	int jlimit = 11;

	if (config_interface_names) {
		interface_names = config_interface_names;
		default_config = false;
		jlimit = 1;
	}

	int fdesc = socket(AF_INET, SOCK_STREAM, 0);

	if (fdesc <= 0) {
		cf_warning(CF_MISC, "can't open socket: %d %s", errno, cf_strerror(errno));
		return(-1);
	}

	struct ifreq req;
	bool done = false;

	for (int i = 0; interface_names[i]; i++) {
		for (int j = 0; j < jlimit; j++) {
			if (default_config) {
				sprintf(req.ifr_name, interface_names[i], j);
			}
			else {
				sprintf(req.ifr_name, "%s", interface_names[i]);
			}

			if (0 == ioctl(fdesc, SIOCGIFHWADDR, &req)) {
				if (cf_ipaddr_get(fdesc, req.ifr_name, node_ipp) == 0) {
					done = true;
					break;
				}
			}

			cf_debug(CF_MISC, "can't get physical address of interface %s: %d %s", req.ifr_name, errno, cf_strerror(errno));
		}

		if (done) {
			break;
		}
	}

	if (! done) {
		if (default_config) {
			struct ifaddrs *interface_addrs = NULL;

			if (getifaddrs(&interface_addrs) == -1) {
				cf_warning(CF_MISC, "getifaddrs failed %d %s", errno, cf_strerror(errno));
				return -1;
			}

			if (! interface_addrs) {
				cf_warning(CF_MISC, "getifaddrs returned NULL");
				return -1;
			}

			struct ifaddrs *ifa;

			for (ifa = interface_addrs; ifa != NULL; ifa = ifa->ifa_next) {
				if (! ifa->ifa_data) {
					continue;
				}

				if (! is_biosdevname(ifa->ifa_name)) {
					continue;
				}

				if (check_mac_and_get_ipaddr(fdesc, ifa->ifa_name, &req, node_ipp)) {
					done = true;
					break;
				}
			}

			for (ifa = interface_addrs; ifa != NULL && (! done); ifa = ifa->ifa_next) {
				if (! ifa->ifa_data) {
					continue;
				}

				if (check_mac_and_get_ipaddr(fdesc, ifa->ifa_name, &req, node_ipp)) {
					done = true;
					break;
				}
			}

			freeifaddrs(interface_addrs);
		}
		else {
			cf_warning(CF_MISC, "can't get physical address of interface name specified in config file, tried %s. fatal: %d %s", interface_names[0], errno, cf_strerror(errno));
			close(fdesc);
			return(-1);
		}
	}

	close(fdesc);

	if (! done) {
		cf_warning(CF_MISC, "Tried eth,bond,wlan,em and list of all available interfaces on device. Failed to retrieve physical address with errno %d %s\n", errno, cf_strerror(errno));
		return(-1);
	}

	/*
	 * Set the hb_addr to be the same as the ip address if the mode is mesh and the hb_addr parameter is empty
	 * Configuration file overrides the automatic node ip detection
	 *	- this gives us a work around in case the node ip is somehow detected wrong in production
	 */
	if (hb_mode == AS_HB_MODE_MESH)	{
		if (*hb_addrp == NULL) {
			*hb_addrp = cf_strdup(*node_ipp);
		}
		cf_info(CF_MISC, "Heartbeat address for mesh: %s", *hb_addrp);
	}

	*id = 0;
	memcpy(id, req.ifr_hwaddr.sa_data, 6);
	memcpy(((byte *)id) + 6, &port, 2);

	cf_debug(CF_MISC, "port %d id %"PRIx64, port, *id);

	return(0);
}