示例#1
0
文件: main.c 项目: lasson-g/polysh
int main(int argc, char *argv[])
{
  FILE *f         = stdin;
  char *rc_file   = absolute_path(RC_FILE);
  char *hist_file = absolute_path(HIST_FILE);

  if (argc > 1) {
    /* On travaille sur un shell script: lui passer les arguments et le lancer */
    add_program_parameters_environ(argc-1, argv+1);
    return execute_script(argv[1]);
  }
  else {
    /* Imprimer une bannière */
    fprintf(stderr, "Bienvenue sur %s version %s\n", SHELL_NAME, VERSION);

    /* lancer éventuellement le script d'initialisation de l'utilisateur*/
    if (access(rc_file, R_OK) == 0)
      execute_script(rc_file);

    /* Passer les paramètres (ici 0 param) et appeler le toplevel de l'interprete */
    add_program_parameters_environ(1, argv);

    /* Gérer l'historique (la sauvegarde se fera automatiquement)  */
    init_history(HISTORY_DEFAULT_SIZE, hist_file);

    /* Lancement du toplevel de l'interprète */
    toplevel(f);
    fprintf(stderr, "Bye\n");
  }

  return EXIT_SUCCESS;
}
示例#2
0
int run_script_auto (struct incbin * incbin, const void * data, const char * script_file, FILE * out) {
  char ** script_lines = NULL;
  char * error = NULL;
  FILE * script = fopen(script_file, "r");
  if (!script) goto error;
  script_lines = read_file_by_lines(script);
  fclose(script);
  char ** output_lines = execute_script(incbin, data, script_lines, &error);
  if (error) goto error;
  if (global_settings.insert_replacement_comment) write_header_comment(incbin, out);
  char ** line;
  char * indent;
  generate_initial_indented_line(&indent, NULL);
  for (line = output_lines; *line; line ++) {
    printf(">>>> %s%s\n", indent, *line);
    fprintf(out, "%s%s\n", indent, *line);
  }
  free(indent);
  destroy_string_array(output_lines);
  destroy_string_array(script_lines);
  return 0;
  error:
  destroy_string_array(script_lines);
  printf("err: %s\n", error);
  free(error);
  return 1;
}
示例#3
0
文件: net_setup.c 项目: Rumko/tinc
/*
  close all open network connections
*/
void close_network_connections(void) {
    avl_node_t *node, *next;
    connection_t *c;
    char *envp[5];
    int i;

    for(node = connection_tree->head; node; node = next) {
        next = node->next;
        c = node->data;
        c->outgoing = NULL;
        terminate_connection(c, false);
    }

    for(list_node_t *node = outgoing_list->head; node; node = node->next) {
        outgoing_t *outgoing = node->data;

        if(outgoing->event)
            event_del(outgoing->event);
    }

    list_delete_list(outgoing_list);

    if(myself && myself->connection) {
        subnet_update(myself, NULL, false);
        terminate_connection(myself->connection, false);
        free_connection(myself->connection);
    }

    for(i = 0; i < listen_sockets; i++) {
        close(listen_socket[i].tcp);
        close(listen_socket[i].udp);
    }

    xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
    xasprintf(&envp[1], "DEVICE=%s", device ? : "");
    xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
    xasprintf(&envp[3], "NAME=%s", myself->name);
    envp[4] = NULL;

    exit_requests();
    exit_edges();
    exit_subnets();
    exit_nodes();
    exit_connections();
    exit_events();

    execute_script("tinc-down", envp);

    if(myport) free(myport);

    for(i = 0; i < 4; i++)
        free(envp[i]);

    close_device();

    return;
}
	void on_resize_bitmap(k3d::bitmap& Output)
	{
		k3d::iscript_engine::context context;
		context["document"] = &document();
		context["node"] = static_cast<k3d::inode*>(this);
		context["output"] = &Output;

		execute_script(context);
	}
示例#5
0
void* dealer_thread(){

  request recived_request;
  int new_conn;
  pid_t son;

  printf("[Dealer]Politica:%s\n",policy);

  sem_wait(sem_full);
  sem_wait(sem_buffer);


  printf("[Schedule]%p\n",buffer);


  recived_request=buffer->request_list[0];
  /*buffer->out++;*/

  new_conn=recived_request.socket_id;
  printf("[Schedule]Recebi do Buffer:%d\n",recived_request.socket_id);

  sem_post(sem_buffer);
  sem_post(sem_empty);

  /* Process request*/
  get_request(new_conn);

  /* Verify if request is for a page or script*/
  if(!strncmp(req_buf,CGI_EXPR,strlen(CGI_EXPR))){
    /*manda para um processo pelos pipes*/
    if((son=fork())==0){
      /*criar nova função para leitura de scripts e envior para a message queue*/
      strcpy(recived_request.request_type,"dinamic");
      strcpy(recived_request.request_file,req_buf);

      execute_script(new_conn);
    }
    waitpid(son,0,0);
  }
  else{
    strcpy(recived_request.request_type,"static");
    strcpy(recived_request.request_file,req_buf);
    pipe_write(0,recived_request);

  }

  sleep(20);
  // Terminate connection with client
  close(new_conn);

  printf("[Dealer]terminei serviço\n");

}
static void run_script(const char *scriptname) {
	char *envp[5];
	int x;

	xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
	xasprintf(&envp[1], "DEVICE=%s", device ? : "");
	xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
	xasprintf(&envp[3], "NAME=%s", myself->name);
	envp[4] = NULL;

	execute_script(scriptname, envp);

	for (x = 0; x < 4; x++) free(envp[x]);
}
示例#7
0
static bool finalize_invitation(connection_t *c, const char *data, uint16_t len) {
	if(strchr(data, '\n')) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Received invalid key from invited node %s (%s)!\n", c->name, c->hostname);
		return false;
	}

	// Create a new host config file
	char filename[PATH_MAX];
	snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
	if(!access(filename, F_OK)) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Host config file for %s (%s) already exists!\n", c->name, c->hostname);
		return false;
	}

	FILE *f = fopen(filename, "w");
	if(!f) {
		logger(DEBUG_ALWAYS, LOG_ERR, "Error trying to create %s: %s\n", filename, strerror(errno));
		return false;
	}

	fprintf(f, "Ed25519PublicKey = %s\n", data);
	fclose(f);

	logger(DEBUG_CONNECTIONS, LOG_INFO, "Key succesfully received from %s (%s)", c->name, c->hostname);

	// Call invitation-accepted script
	char *envp[7] = {NULL};
	char *address, *port;

	xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
        xasprintf(&envp[1], "DEVICE=%s", device ? : "");
        xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
        xasprintf(&envp[3], "NODE=%s", c->name);
	sockaddr2str(&c->address, &address, &port);
	xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
	xasprintf(&envp[5], "NAME=%s", myself->name);

	execute_script("invitation-accepted", envp);

	for(int i = 0; envp[i] && i < 7; i++)
		free(envp[i]);

	sptps_send_record(&c->sptps, 2, data, 0);
	return true;
}
示例#8
0
	void on_update_color(k3d::color& Output)
	{
		k3d::iscript_engine::context context;
		context["document"] = &document();
		context["node"] = static_cast<k3d::inode*>(this);
		context["output"] = k3d::color(1, 1, 1);

		execute_script(context);

		if(context["output"].type() == typeid(k3d::color))
		{
			Output = boost::any_cast<k3d::color>(context["output"]);
			return;
		}

		k3d::log() << error << "unsupported output type: " << k3d::demangle(context["output"].type()) << std::endl;
		Output = k3d::color(1, 1, 1);
	}
示例#9
0
int run_script (struct incbin * incbin, const void * data, FILE * out) {
  printf("Script file: ");
  char * script_name = read_line(stdin);
  if (!*script_name) {
    free(script_name);
    return 0;
  }
  FILE * script = fopen(script_name, "r");
  free(script_name);
  if (!script) {
    printf("err: could not open script file\n");
    return 0;
  }
  char ** script_lines = read_file_by_lines(script);
  fclose(script);
  char * error = NULL;
  char ** output_lines = execute_script(incbin, data, script_lines, &error);
  destroy_string_array(script_lines);
  return handle_script_output(output_lines, error, incbin, out);
}
示例#10
0
int main(int argc, const char** argv) {
  int res = -1;

  // Call the glue first.
  wasm_llvm_init();

  res = execute_script();

  if (res == -1) {
    return EXIT_SUCCESS;
    fprintf(stderr, "Executed script, success\n");
  } else {
    fprintf(stderr, "Executed script, failure for assertion line %d\n", res);

    if (argc < 2) {
      fprintf(stderr, "No information on file used\n");
    } else {
      PrintLine(argv[1], res);
    }

    return EXIT_FAILURE;
  }
}
示例#11
0
	k3d::bool_t execute(k3d::iscript_engine::context& Context)
	{
		return execute_script(Context);
	}
示例#12
0
/******************************************************************************
 *                                                                            *
 * Function: node_process_command                                             *
 *                                                                            *
 * Purpose: process command received from a master node or php                *
 *                                                                            *
 * Return value:  SUCCEED - processed successfully                            *
 *                FAIL - an error occurred                                    *
 *                                                                            *
 ******************************************************************************/
int	node_process_command(zbx_sock_t *sock, const char *data, struct zbx_json_parse *jp)
{
	char		*result = NULL, *send = NULL, tmp[64];
	int		nodeid = -1, next_nodeid, ret = FAIL;
	zbx_uint64_t	scriptid, hostid;
	struct zbx_json	j;

	zabbix_log(LOG_LEVEL_DEBUG, "In node_process_command()");

	zbx_json_init(&j, ZBX_JSON_STAT_BUF_LEN);

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_NODEID, tmp, sizeof(tmp)) ||
			FAIL == is_uint31(tmp, &nodeid))
	{
		result = zbx_dsprintf(result, "Failed to parse command request tag: %s.", ZBX_PROTO_TAG_NODEID);
		goto finish;
	}

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SCRIPTID, tmp, sizeof(tmp)) ||
			FAIL == is_uint64(tmp, &scriptid))
	{
		result = zbx_dsprintf(result, "Failed to parse command request tag: %s.", ZBX_PROTO_TAG_SCRIPTID);
		goto finish;
	}

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOSTID, tmp, sizeof(tmp)) ||
			FAIL == is_uint64(tmp, &hostid))
	{
		result = zbx_dsprintf(result, "Failed to parse command request tag: %s.", ZBX_PROTO_TAG_HOSTID);
		goto finish;
	}

	if (nodeid == CONFIG_NODEID)
	{
		if (SUCCEED == (ret = execute_script(scriptid, hostid, &result)))
		{
			zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_SUCCESS, ZBX_JSON_TYPE_STRING);
			zbx_json_addstring(&j, ZBX_PROTO_TAG_DATA, result, ZBX_JSON_TYPE_STRING);
			send = j.buffer;
		}
	}
	else if (SUCCEED == get_next_point_to_node(CONFIG_NODEID, nodeid, &next_nodeid))
	{
		zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Sending command for Node %d to Node %d",
				CONFIG_NODEID, nodeid, next_nodeid);

		if (SUCCEED == (ret = send_script(next_nodeid, data, &result)))
			send = result;
	}
	else
		result = zbx_dsprintf(result, "NODE %d: Unknown Node ID [%d].", CONFIG_NODEID, nodeid);
finish:
	if (FAIL == ret)
	{
		zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&j, ZBX_PROTO_TAG_INFO, (NULL != result ? result : "Unknown error."),
				ZBX_JSON_TYPE_STRING);
		send = j.buffer;
	}

	alarm(CONFIG_TIMEOUT);
	if (SUCCEED != zbx_tcp_send_raw(sock, send))
	{
		zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Error sending result of command to node %d",
				CONFIG_NODEID, nodeid);
	}
	else
	{
		zabbix_log(LOG_LEVEL_DEBUG, "NODE %d: Sending back command '%s' result '%s'",
				CONFIG_NODEID, data, send);
	}
	alarm(0);

	zbx_json_free(&j);
	zbx_free(result);

	return ret;
}
示例#13
0
void cli_handler(char *buf)
{
	if(buf)
	{
		if(g_context.ttymode)
		{
			if(strncmp(buf, "~.", 2) == 0)
			{
				char prompt[PATH_MAX];

				g_context.ttymode = 0;
				rl_callback_handler_remove();
				snprintf(prompt, PATH_MAX, "%s> ", g_context.currpath);
				rl_callback_handler_install(prompt, cli_handler);
			}
			else if(g_context.outsock >= 0)
			{
				char b[1024];

				snprintf(b, sizeof(b), "%s\n", buf);
				write(g_context.outsock, b, strlen(b));
			}

			return;
		}

		while(isspace(*buf))
		{
			buf++;
		}

		if(*buf == 0)
		{
			if(g_context.asmmode)
			{
				char prompt[PATH_MAX];
				g_context.asmmode = 0;
				g_context.asmaddr = 0;
				rl_callback_handler_remove();
				snprintf(prompt, PATH_MAX, "%s> ", g_context.currpath);
				rl_callback_handler_install(prompt, cli_handler);
			}
			return;
		}

		if(in_script())
		{
			/* When a script is running only accept stop */
			if(strcmp(buf, "stop") == 0)
			{
				close_script();
			}

			return;
		}

		if(g_context.asmmode)
		{
			char cmd[1024];
			/* Do assembler */
			unsigned int opcode;
			if(asmAssemble(buf, g_context.asmaddr, &opcode) == 0)
			{
				sprintf(cmd, "pokew 0x%08X 0x%08X ", g_context.asmaddr, opcode);
				execute_line(cmd);
			}

			return;
		}

		add_history(buf);
		if(buf[0] == '!')
		{
			if(strncmp(&buf[1], "cd ", 3) == 0)
			{
				chdir(&buf[4]);
			}
			else
			{
				system(&buf[1]);
			}
			return;
		}
		else if(buf[0] == '@')
		{
			if(g_context.fssock >= 0)
			{
				(void) write(g_context.fssock, &buf[1], strlen(&buf[1]));
			}
			return;
		}
		else if(buf[0] == '%')
		{
			execute_script(&buf[1]);
			return;
		}

		execute_line(buf);
	}
	else
	{
		shutdown_app();
		exit(0);
	}
}
示例#14
0
int main(int argc, char *argv[]) {

	int rv = -1;

	const char *device = NULL;
	const char *scriptname = NULL;

	// wait for socket if not there right away?
	int dowait = 0;

	terminal_init();


        int i=1;
        while(i<argc && argv[i][0]=='-' && argv[i][1] != 0) {
          	switch(argv[i][1]) {
            	case '?':
                	assert_single_char(argv[i]);
                	usage(EXIT_SUCCESS);    /* usage() exits already */
                	break;
            	case 'd':
                	assert_single_char(argv[i]);
                	if (i < argc-1) {
                  		i++;
                  		device = argv[i];
                  		log_info("main: device = %s\n", device);
                	} else {
                  		log_error("-d requires <device> parameter\n");
                  		exit(1);
                	}
                	break;
		case 'v':
			set_verbose();
			break;
		case 't':
			trace = 1;
			break;
		case 'w':
			dowait = 1;
			break;
            	default:
                	log_error("Unknown command line option %s\n", argv[i]);
                	usage(1);
                	break;
          	}
          	i++;
        }

	// next parameter is the script name
	if (i >= argc) {
		log_error("Script name parameter missing!\n");
		return -1;
	}

	scriptname = argv[i];
	i++;

	registry_t *script = load_script_from_file(scriptname);

	if (script != NULL) {

		int sockfd = socket_open(device, dowait);
	
		if (sockfd >= 0) {

			rv = execute_script(sockfd, script);
		}
	}

	
	return rv;
}
示例#15
0
/******************************************************************************
 *                                                                            *
 * Function: node_process_command                                             *
 *                                                                            *
 * Purpose: process command received from a master node or php                *
 *                                                                            *
 * Parameters:                                                                *
 *                                                                            *
 * Return value:  SUCCEED - processed successfully                            *
 *                FAIL - an error occurred                                    *
 *                                                                            *
 * Author: Alexander Vladishev                                                *
 *                                                                            *
 * Comments:                                                                  *
 *                                                                            *
 ******************************************************************************/
int	node_process_command(zbx_sock_t *sock, const char *data, struct zbx_json_parse *jp)
{
	char		*result = NULL, *send, tmp[64];
	const char	*response;
	int		nodeid, next_nodeid, ret = FAIL;
	zbx_uint64_t	scriptid, hostid;
	struct zbx_json	j;

	zabbix_log(LOG_LEVEL_DEBUG, "In node_process_command()");

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_NODEID, tmp, sizeof(tmp)))
		return FAIL;
	nodeid = atoi(tmp);

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_SCRIPTID, tmp, sizeof(tmp)))
		return FAIL;
	ZBX_STR2UINT64(scriptid, tmp);

	if (SUCCEED != zbx_json_value_by_name(jp, ZBX_PROTO_TAG_HOSTID, tmp, sizeof(tmp)))
		return FAIL;
	ZBX_STR2UINT64(hostid, tmp);

	zbx_json_init(&j, 256);

	if (nodeid == CONFIG_NODEID)
	{
		ret = execute_script(scriptid, hostid, &result);

		response = (FAIL == ret) ? ZBX_PROTO_VALUE_FAILED : ZBX_PROTO_VALUE_SUCCESS;

		zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, response, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&j, ZBX_PROTO_TAG_VALUE, result, ZBX_JSON_TYPE_STRING);
		send = j.buffer;
	}
	else if (SUCCEED == get_next_point_to_node(CONFIG_NODEID, nodeid, &next_nodeid))
	{
		zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Sending command for Node %d to Node %d",
				CONFIG_NODEID, nodeid, next_nodeid);

		if (FAIL == (ret = send_script(next_nodeid, data, &result)))
		{
			zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
			zbx_json_addstring(&j, ZBX_PROTO_TAG_VALUE, result, ZBX_JSON_TYPE_STRING);
			send = j.buffer;
		}
		else
			send = result;
	}
	else
	{
		result = zbx_dsprintf(result, "NODE %d: Unknown Node ID [%d]",
				CONFIG_NODEID, nodeid);

		zbx_json_addstring(&j, ZBX_PROTO_TAG_RESPONSE, ZBX_PROTO_VALUE_FAILED, ZBX_JSON_TYPE_STRING);
		zbx_json_addstring(&j, ZBX_PROTO_TAG_VALUE, result, ZBX_JSON_TYPE_STRING);
		send = j.buffer;
	}

	alarm(CONFIG_TIMEOUT);
	if (zbx_tcp_send_raw(sock, send) != SUCCEED)
	{
		zabbix_log(LOG_LEVEL_WARNING, "NODE %d: Error sending result of command to node %d",
			CONFIG_NODEID,
			nodeid);
	}
	alarm(0);

	zbx_json_free(&j);
	zbx_free(result);

	return SUCCEED;
}
示例#16
0
文件: invitation.c 项目: xentec/tinc
int cmd_invite(int argc, char *argv[]) {
	if(argc < 2) {
		fprintf(stderr, "Not enough arguments!\n");
		return 1;
	}

	// Check validity of the new node's name
	if(!check_id(argv[1])) {
		fprintf(stderr, "Invalid name for node.\n");
		return 1;
	}

	char *myname = get_my_name(true);
	if(!myname)
		return 1;

	// Ensure no host configuration file with that name exists
	char filename[PATH_MAX];
	snprintf(filename, sizeof filename, "%s" SLASH "hosts" SLASH "%s", confbase, argv[1]);
	if(!access(filename, F_OK)) {
		fprintf(stderr, "A host config file for %s already exists!\n", argv[1]);
		return 1;
	}

	// If a daemon is running, ensure no other nodes know about this name
	bool found = false;
	if(connect_tincd(false)) {
		sendline(fd, "%d %d", CONTROL, REQ_DUMP_NODES);

		while(recvline(fd, line, sizeof line)) {
			char node[4096];
			int code, req;
			if(sscanf(line, "%d %d %s", &code, &req, node) != 3)
				break;
			if(!strcmp(node, argv[1]))
				found = true;
		}

		if(found) {
			fprintf(stderr, "A node with name %s is already known!\n", argv[1]);
			return 1;
		}
	}

	snprintf(filename, sizeof filename, "%s" SLASH "invitations", confbase);
	if(mkdir(filename, 0700) && errno != EEXIST) {
		fprintf(stderr, "Could not create directory %s: %s\n", filename, strerror(errno));
		return 1;
	}

	// Count the number of valid invitations, clean up old ones
	DIR *dir = opendir(filename);
	if(!dir) {
		fprintf(stderr, "Could not read directory %s: %s\n", filename, strerror(errno));
		return 1;
	}

	errno = 0;
	int count = 0;
	struct dirent *ent;
	time_t deadline = time(NULL) - 604800; // 1 week in the past

	while((ent = readdir(dir))) {
		if(strlen(ent->d_name) != 24)
			continue;
		char invname[PATH_MAX];
		struct stat st;
		snprintf(invname, sizeof invname, "%s" SLASH "%s", filename, ent->d_name);
		if(!stat(invname, &st)) {
			if(deadline < st.st_mtime)
				count++;
			else
				unlink(invname);
		} else {
			fprintf(stderr, "Could not stat %s: %s\n", invname, strerror(errno));
			errno = 0;
		}
	}

	closedir(dir);

	if(errno) {
		fprintf(stderr, "Error while reading directory %s: %s\n", filename, strerror(errno));
		return 1;
	}
		
	ecdsa_t *key;
	snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "ed25519_key.priv", confbase);

	// Remove the key if there are no outstanding invitations.
	if(!count)
		unlink(filename);

	// Create a new key if necessary.
	FILE *f = fopen(filename, "r");
	if(!f) {
		if(errno != ENOENT) {
			fprintf(stderr, "Could not read %s: %s\n", filename, strerror(errno));
			return 1;
		}

		key = ecdsa_generate();
		if(!key)
			return 1;
		f = fopen(filename, "w");
		if(!f) {
			fprintf(stderr, "Could not write %s: %s\n", filename, strerror(errno));
			return 1;
		}
		chmod(filename, 0600);
		if(!ecdsa_write_pem_private_key(key, f)) {
			fprintf(stderr, "Could not write ECDSA private key\n");
			fclose(f);
			return 1;
		}
		fclose(f);

		if(connect_tincd(false))
			sendline(fd, "%d %d", CONTROL, REQ_RELOAD);
	} else {
		key = ecdsa_read_pem_private_key(f);
		fclose(f);
		if(!key)
			fprintf(stderr, "Could not read private key from %s\n", filename);
	}

	if(!key)
		return 1;

	// Create a hash of the key.
	char hash[64];
	char *fingerprint = ecdsa_get_base64_public_key(key);
	sha512(fingerprint, strlen(fingerprint), hash);
	b64encode_urlsafe(hash, hash, 18);

	// Create a random cookie for this invitation.
	char cookie[25];
	randomize(cookie, 18);

	// Create a filename that doesn't reveal the cookie itself
	char buf[18 + strlen(fingerprint)];
	char cookiehash[64];
	memcpy(buf, cookie, 18);
	memcpy(buf + 18, fingerprint, sizeof buf - 18);
	sha512(buf, sizeof buf, cookiehash);
	b64encode_urlsafe(cookiehash, cookiehash, 18);

	b64encode_urlsafe(cookie, cookie, 18);

	// Create a file containing the details of the invitation.
	snprintf(filename, sizeof filename, "%s" SLASH "invitations" SLASH "%s", confbase, cookiehash);
	int ifd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600);
	if(!ifd) {
		fprintf(stderr, "Could not create invitation file %s: %s\n", filename, strerror(errno));
		return 1;
	}
	f = fdopen(ifd, "w");
	if(!f)
		abort();

	// Get the local address
	char *address = get_my_hostname();

	// Fill in the details.
	fprintf(f, "Name = %s\n", argv[1]);
	if(netname)
		fprintf(f, "NetName = %s\n", netname);
	fprintf(f, "ConnectTo = %s\n", myname);

	// Copy Broadcast and Mode
	FILE *tc = fopen(tinc_conf, "r");
	if(tc) {
		char buf[1024];
		while(fgets(buf, sizeof buf, tc)) {
			if((!strncasecmp(buf, "Mode", 4) && strchr(" \t=", buf[4]))
					|| (!strncasecmp(buf, "Broadcast", 9) && strchr(" \t=", buf[9]))) {
				fputs(buf, f);
				// Make sure there is a newline character.
				if(!strchr(buf, '\n'))
					fputc('\n', f);
			}
		}
		fclose(tc);
	}

	fprintf(f, "#---------------------------------------------------------------#\n");
	fprintf(f, "Name = %s\n", myname);

	char filename2[PATH_MAX];
	snprintf(filename2, sizeof filename2, "%s" SLASH "hosts" SLASH "%s", confbase, myname);
	fcopy(f, filename2);
	fclose(f);

	// Create an URL from the local address, key hash and cookie
	char *url;
	xasprintf(&url, "%s/%s%s", address, hash, cookie);

	// Call the inviation-created script
	char *envp[6] = {};
	xasprintf(&envp[0], "NAME=%s", myname);
	xasprintf(&envp[1], "NETNAME=%s", netname);
	xasprintf(&envp[2], "NODE=%s", argv[1]);
	xasprintf(&envp[3], "INVITATION_FILE=%s", filename);
	xasprintf(&envp[4], "INVITATION_URL=%s", url);
	execute_script("invitation-created", envp);
	for(int i = 0; i < 6 && envp[i]; i++)
		free(envp[i]);

	puts(url);
	free(url);
	free(address);

	return 0;
}
示例#17
0
文件: net_setup.c 项目: Rumko/tinc
/*
  Configure node_t myself and set up the local sockets (listen only)
*/
bool setup_myself(void) {
    config_t *cfg;
    subnet_t *subnet;
    char *name, *hostname, *mode, *afname, *cipher, *digest;
    char *fname = NULL;
    char *address = NULL;
    char *envp[5];
    struct addrinfo *ai, *aip, hint = {0};
    bool choice;
    int i, err;
    int replaywin_int;

    myself = new_node();
    myself->connection = new_connection();

    myself->hostname = xstrdup("MYSELF");
    myself->connection->hostname = xstrdup("MYSELF");

    myself->connection->options = 0;
    myself->connection->protocol_version = PROT_CURRENT;

    if(!get_config_string(lookup_config(config_tree, "Name"), &name)) {	/* Not acceptable */
        logger(LOG_ERR, "Name for tinc daemon required!");
        return false;
    }

    if(!check_id(name)) {
        logger(LOG_ERR, "Invalid name for myself!");
        free(name);
        return false;
    }

    myself->name = name;
    myself->connection->name = xstrdup(name);
    xasprintf(&fname, "%s/hosts/%s", confbase, name);
    read_config_options(config_tree, name);
    read_config_file(config_tree, fname);
    free(fname);

    if(!read_rsa_private_key())
        return false;

    if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
        myport = xstrdup("655");

    if(!atoi(myport)) {
        struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
        sockaddr_t sa;
        if(!ai || !ai->ai_addr)
            return false;
        free(myport);
        memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
        sockaddr2str(&sa, NULL, &myport);
    }

    /* Read in all the subnets specified in the host configuration file */

    cfg = lookup_config(config_tree, "Subnet");

    while(cfg) {
        if(!get_config_subnet(cfg, &subnet))
            return false;

        subnet_add(myself, subnet);

        cfg = lookup_config_next(config_tree, cfg);
    }

    /* Check some options */

    if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
        myself->options |= OPTION_INDIRECT;

    if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
        myself->options |= OPTION_TCPONLY;

    if(myself->options & OPTION_TCPONLY)
        myself->options |= OPTION_INDIRECT;

    get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
    get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
    get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
    strictsubnets |= tunnelserver;

    if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
        if(!strcasecmp(mode, "router"))
            routing_mode = RMODE_ROUTER;
        else if(!strcasecmp(mode, "switch"))
            routing_mode = RMODE_SWITCH;
        else if(!strcasecmp(mode, "hub"))
            routing_mode = RMODE_HUB;
        else {
            logger(LOG_ERR, "Invalid routing mode!");
            return false;
        }
        free(mode);
    }

    if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
        if(!strcasecmp(mode, "off"))
            forwarding_mode = FMODE_OFF;
        else if(!strcasecmp(mode, "internal"))
            forwarding_mode = FMODE_INTERNAL;
        else if(!strcasecmp(mode, "kernel"))
            forwarding_mode = FMODE_KERNEL;
        else {
            logger(LOG_ERR, "Invalid forwarding mode!");
            return false;
        }
        free(mode);
    }

    choice = true;
    get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
    if(choice)
        myself->options |= OPTION_PMTU_DISCOVERY;

    choice = true;
    get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
    if(choice)
        myself->options |= OPTION_CLAMP_MSS;

    get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);

#if !defined(SOL_IP) || !defined(IP_TOS)
    if(priorityinheritance)
        logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
#endif

    if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
        macexpire = 600;

    if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
        if(maxtimeout <= 0) {
            logger(LOG_ERR, "Bogus maximum timeout!");
            return false;
        }
    } else
        maxtimeout = 900;

    if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
        if(udp_rcvbuf <= 0) {
            logger(LOG_ERR, "UDPRcvBuf cannot be negative!");
            return false;
        }
    }

    if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
        if(udp_sndbuf <= 0) {
            logger(LOG_ERR, "UDPSndBuf cannot be negative!");
            return false;
        }
    }

    if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
        if(replaywin_int < 0) {
            logger(LOG_ERR, "ReplayWindow cannot be negative!");
            return false;
        }
        replaywin = (unsigned)replaywin_int;
    }

    if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
        if(!strcasecmp(afname, "IPv4"))
            addressfamily = AF_INET;
        else if(!strcasecmp(afname, "IPv6"))
            addressfamily = AF_INET6;
        else if(!strcasecmp(afname, "any"))
            addressfamily = AF_UNSPEC;
        else {
            logger(LOG_ERR, "Invalid address family!");
            return false;
        }
        free(afname);
    }

    get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);

    /* Generate packet encryption key */

    if(get_config_string
            (lookup_config(config_tree, "Cipher"), &cipher)) {
        if(!strcasecmp(cipher, "none")) {
            myself->incipher = NULL;
        } else {
            myself->incipher = EVP_get_cipherbyname(cipher);

            if(!myself->incipher) {
                logger(LOG_ERR, "Unrecognized cipher type!");
                return false;
            }
        }
    } else
        myself->incipher = EVP_bf_cbc();

    if(myself->incipher)
        myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len;
    else
        myself->inkeylength = 1;

    myself->connection->outcipher = EVP_bf_ofb();

    if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
        keylifetime = 3600;

    keyexpires = now + keylifetime;

    /* Check if we want to use message authentication codes... */

    if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
        if(!strcasecmp(digest, "none")) {
            myself->indigest = NULL;
        } else {
            myself->indigest = EVP_get_digestbyname(digest);

            if(!myself->indigest) {
                logger(LOG_ERR, "Unrecognized digest type!");
                return false;
            }
        }
    } else
        myself->indigest = EVP_sha1();

    myself->connection->outdigest = EVP_sha1();

    if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
        if(myself->indigest) {
            if(myself->inmaclength > myself->indigest->md_size) {
                logger(LOG_ERR, "MAC length exceeds size of digest!");
                return false;
            } else if(myself->inmaclength < 0) {
                logger(LOG_ERR, "Bogus MAC length!");
                return false;
            }
        }
    } else
        myself->inmaclength = 4;

    myself->connection->outmaclength = 0;

    /* Compression */

    if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
        if(myself->incompression < 0 || myself->incompression > 11) {
            logger(LOG_ERR, "Bogus compression level!");
            return false;
        }
    } else
        myself->incompression = 0;

    myself->connection->outcompression = 0;

    /* Done */

    myself->nexthop = myself;
    myself->via = myself;
    myself->status.reachable = true;
    node_add(myself);

    graph();

    if(strictsubnets)
        load_all_subnets();

    /* Open device */

    if(!setup_device())
        return false;

    /* Run tinc-up script to further initialize the tap interface */
    xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
    xasprintf(&envp[1], "DEVICE=%s", device ? : "");
    xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
    xasprintf(&envp[3], "NAME=%s", myself->name);
    envp[4] = NULL;

    execute_script("tinc-up", envp);

    for(i = 0; i < 5; i++)
        free(envp[i]);

    /* Run subnet-up scripts for our own subnets */

    subnet_update(myself, NULL, true);

    /* Open sockets */

    get_config_string(lookup_config(config_tree, "BindToAddress"), &address);

    hint.ai_family = addressfamily;
    hint.ai_socktype = SOCK_STREAM;
    hint.ai_protocol = IPPROTO_TCP;
    hint.ai_flags = AI_PASSIVE;

    err = getaddrinfo(address, myport, &hint, &ai);

    if(err || !ai) {
        logger(LOG_ERR, "System call `%s' failed: %s", "getaddrinfo",
               gai_strerror(err));
        return false;
    }

    listen_sockets = 0;

    for(aip = ai; aip; aip = aip->ai_next) {
        listen_socket[listen_sockets].tcp =
            setup_listen_socket((sockaddr_t *) aip->ai_addr);

        if(listen_socket[listen_sockets].tcp < 0)
            continue;

        listen_socket[listen_sockets].udp =
            setup_vpn_in_socket((sockaddr_t *) aip->ai_addr);

        if(listen_socket[listen_sockets].udp < 0)
            continue;

        ifdebug(CONNECTIONS) {
            hostname = sockaddr2hostname((sockaddr_t *) aip->ai_addr);
            logger(LOG_NOTICE, "Listening on %s", hostname);
            free(hostname);
        }

        memcpy(&listen_socket[listen_sockets].sa, aip->ai_addr, aip->ai_addrlen);
        listen_sockets++;
    }

    freeaddrinfo(ai);

    if(listen_sockets)
        logger(LOG_NOTICE, "Ready");
    else {
        logger(LOG_ERR, "Unable to create any listening socket!");
        return false;
    }

    return true;
}
示例#18
0
// the constructor
bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif,
				       const char *macaddr,
				       eth_rx_handler_t rxh,
				       void *rxarg,
				       char *script)
{
  int flags;
  char filename[BX_PATHNAME_LEN];
  if (strncmp (netif, "tap", 3) != 0) {
    BX_PANIC (("eth_tap: interface name (%s) must be tap0..tap15", netif));
  }
  sprintf (filename, "/dev/%s", netif);

#if defined(__linux__)
  // check if the TAP devices is running, and turn on ARP.  This is based
  // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock < 0) {
    BX_PANIC (("socket creation: %s", strerror(errno)));
    return;
  }
  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name));
  if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
    BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror(errno)));
    close(sock);
    return;
  }
  if (!(ifr.ifr_flags & IFF_RUNNING)) {
    BX_PANIC (("%s device is not running", netif));
    close(sock);
    return;
  }
  if ((ifr.ifr_flags & IFF_NOARP)){
    BX_INFO(("turn on ARP for %s device", netif));
    ifr.ifr_flags &= ~IFF_NOARP;
    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
      BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno)));
      close(sock);
      return;
    }
  }
  close(sock);
#endif

  fd = open (filename, O_RDWR);
  if (fd < 0) {
    BX_PANIC(("open failed on %s: %s", netif, strerror(errno)));
    return;
  }

  /* set O_ASYNC flag so that we can poll with read() */
  if ((flags = fcntl(fd, F_GETFL)) < 0) {
    BX_PANIC(("getflags on tap device: %s", strerror(errno)));
  }
  flags |= O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) < 0) {
    BX_PANIC(("set tap device flags: %s", strerror(errno)));
  }

  BX_INFO(("eth_tap: opened %s device", netif));

  /* Execute the configuration script */
  char intname[IFNAMSIZ];
  strcpy(intname,netif);
  if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0))
  {
    if (execute_script(script, intname) < 0)
      BX_ERROR(("execute script '%s' on %s failed", script, intname));
  }

  // Start the rx poll
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
				1, 1, "eth_tap"); // continuous, active
  this->rxh   = rxh;
  this->rxarg = rxarg;
  memcpy(&guest_macaddr[0], macaddr, 6);
#if BX_ETH_TAP_LOGGING
  // eventually Bryce wants txlog to dump in pcap format so that
  // tcpdump -r FILE can read it and interpret packets.
  txlog = fopen ("ne2k-tx.log", "wb");
  if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
  txlog_txt = fopen ("ne2k-txdump.txt", "wb");
  if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
  fprintf (txlog_txt, "tap packetmover readable log file\n");
  fprintf (txlog_txt, "net IF = %s\n", netif);
  fprintf (txlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf (txlog_txt, "\n--\n");
  fflush (txlog_txt);

  rxlog = fopen ("ne2k-rx.log", "wb");
  if (!rxlog) BX_PANIC (("open ne2k-rx.log failed"));
  rxlog_txt = fopen ("ne2k-rxdump.txt", "wb");
  if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed"));
  fprintf (rxlog_txt, "tap packetmover readable log file\n");
  fprintf (rxlog_txt, "net IF = %s\n", netif);
  fprintf (rxlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf (rxlog_txt, "\n--\n");
  fflush (rxlog_txt);

#endif
}
示例#19
0
文件: graph.c 项目: eminarcissus/tinc
static void sssp_bfs(void) {
	avl_node_t *node, *next, *to;
	edge_t *e;
	node_t *n;
	list_t *todo_list;
	list_node_t *from, *todonext;
	bool indirect;
	char *name;
	char *address, *port;
	char *envp[7];
	int i;

	todo_list = list_alloc(NULL);

	/* Clear visited status on nodes */

	for(node = node_tree->head; node; node = node->next) {
		n = node->data;
		n->status.visited = false;
		n->status.indirect = true;
	}

	/* Begin with myself */

	myself->status.visited = true;
	myself->status.indirect = false;
	myself->nexthop = myself;
	myself->prevedge = NULL;
	myself->via = myself;
	list_insert_head(todo_list, myself);

	/* Loop while todo_list is filled */

	for(from = todo_list->head; from; from = todonext) {	/* "from" is the node from which we start */
		n = from->data;

		for(to = n->edge_tree->head; to; to = to->next) {	/* "to" is the edge connected to "from" */
			e = to->data;

			if(!e->reverse)
				continue;

			/* Situation:

				   /
				  /
			   ----->(n)---e-->(e->to)
				  \
				   \

			   Where e is an edge, (n) and (e->to) are nodes.
			   n->address is set to the e->address of the edge left of n to n.
			   We are currently examining the edge e right of n from n:

			   - If edge e provides for better reachability of e->to, update
			     e->to and (re)add it to the todo_list to (re)examine the reachability
			     of nodes behind it.
			 */

			indirect = n->status.indirect || e->options & OPTION_INDIRECT;

			if(e->to->status.visited
			   && (!e->to->status.indirect || indirect))
				continue;

			e->to->status.visited = true;
			e->to->status.indirect = indirect;
			e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
			e->to->prevedge = e;
			e->to->via = indirect ? n->via : e->to;
			e->to->options = e->options;

			if(e->to->address.sa.sa_family == AF_UNSPEC && e->address.sa.sa_family != AF_UNKNOWN)
				update_node_udp(e->to, &e->address);

			list_insert_tail(todo_list, e->to);
		}

		todonext = from->next;
		list_delete_node(todo_list, from);
	}

	list_free(todo_list);

	/* Check reachability status. */

	for(node = node_tree->head; node; node = next) {
		next = node->next;
		n = node->data;

		if(n->status.visited != n->status.reachable) {
			n->status.reachable = !n->status.reachable;

			if(n->status.reachable) {
				ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became reachable",
					   n->name, n->hostname);
			} else {
				ifdebug(TRAFFIC) logger(LOG_DEBUG, "Node %s (%s) became unreachable",
					   n->name, n->hostname);
			}

			/* TODO: only clear status.validkey if node is unreachable? */

			n->status.validkey = false;
			n->last_req_key = 0;

			n->maxmtu = MTU;
			n->minmtu = 0;
			n->mtuprobes = 0;

			if(n->mtuevent) {
				event_del(n->mtuevent);
				n->mtuevent = NULL;
			}

			xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
			xasprintf(&envp[1], "DEVICE=%s", device ? : "");
			xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
			xasprintf(&envp[3], "NODE=%s", n->name);
			sockaddr2str(&n->address, &address, &port);
			xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
			xasprintf(&envp[5], "REMOTEPORT=%s", port);
			envp[6] = NULL;

			execute_script(n->status.reachable ? "host-up" : "host-down", envp);

			xasprintf(&name,
					 n->status.reachable ? "hosts/%s-up" : "hosts/%s-down",
					 n->name);
			execute_script(name, envp);

			free(name);
			free(address);
			free(port);

			for(i = 0; i < 6; i++)
				free(envp[i]);

			subnet_update(n, NULL, n->status.reachable);

			if(!n->status.reachable)
				update_node_udp(n, NULL);
			else if(n->connection)
				send_ans_key(n);
		}
	}
示例#20
0
文件: subnet.c 项目: Phillyun/tinc
void subnet_update(node_t *owner, subnet_t *subnet, bool up) {
	avl_node_t *node;
	int i;
	char *envp[10] = {NULL};
	char netstr[MAXNETSTR];
	char *name, *address, *port;
	char empty[] = "";

	// Prepare environment variables to be passed to the script

	xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
	xasprintf(&envp[1], "DEVICE=%s", device ? : "");
	xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
	xasprintf(&envp[3], "NODE=%s", owner->name);

	if(owner != myself) {
		sockaddr2str(&owner->address, &address, &port);
		// 4 and 5 are reserved for SUBNET and WEIGHT
		xasprintf(&envp[6], "REMOTEADDRESS=%s", address);
		xasprintf(&envp[7], "REMOTEPORT=%s", port);
		free(port);
		free(address);
	}

	xasprintf(&envp[8], "NAME=%s", myself->name);

	name = up ? "subnet-up" : "subnet-down";

	if(!subnet) {
		for(node = owner->subnet_tree->head; node; node = node->next) {
			subnet = node->data;
			if(!net2str(netstr, sizeof netstr, subnet))
				continue;
			// Strip the weight from the subnet, and put it in its own environment variable
			char *weight = strchr(netstr, '#');
			if(weight)
				*weight++ = 0;
			else
				weight = empty;

			// Prepare the SUBNET and WEIGHT variables
			if(envp[4])
				free(envp[4]);
			if(envp[5])
				free(envp[5]);
			xasprintf(&envp[4], "SUBNET=%s", netstr);
			xasprintf(&envp[5], "WEIGHT=%s", weight);

			execute_script(name, envp);
		}
	} else {
		if(net2str(netstr, sizeof netstr, subnet)) {
			// Strip the weight from the subnet, and put it in its own environment variable
			char *weight = strchr(netstr, '#');
			if(weight)
				*weight++ = 0;
			else
				weight = empty;

			// Prepare the SUBNET and WEIGHT variables
			xasprintf(&envp[4], "SUBNET=%s", netstr);
			xasprintf(&envp[5], "WEIGHT=%s", weight);

			execute_script(name, envp);
		}
	}

	for(i = 0; envp[i] && i < 9; i++)
		free(envp[i]);
}
示例#21
0
文件: eth_tap.cpp 项目: iver6/BA
// the constructor
bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif,
                                     const char *macaddr,
                                     eth_rx_handler_t rxh,
                                     bx_devmodel_c *dev,
                                     const char *script)
{
  int flags;
  char filename[BX_PATHNAME_LEN];

  this->netdev = dev;
  if (strncmp (netif, "tap", 3) != 0) {
    BX_PANIC(("eth_tap: interface name (%s) must be tap0..tap15", netif));
  }
#if defined(__sun__)
  strcpy(filename,"/dev/tap"); /* PD - device on Solaris is always the same */
#else
  sprintf(filename, "/dev/%s", netif);
#endif

#if defined(__linux__)
  // check if the TAP devices is running, and turn on ARP.  This is based
  // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  if (sock < 0) {
    BX_PANIC(("socket creation: %s", strerror(errno)));
    return;
  }
  struct ifreq ifr;
  memset(&ifr, 0, sizeof(ifr));
  strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name));
  if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
    BX_PANIC(("SIOCGIFFLAGS on %s: %s", netif, strerror(errno)));
    close(sock);
    return;
  }
  if (!(ifr.ifr_flags & IFF_RUNNING)) {
    BX_PANIC(("%s device is not running", netif));
    close(sock);
    return;
  }
  if ((ifr.ifr_flags & IFF_NOARP)){
    BX_INFO(("turn on ARP for %s device", netif));
    ifr.ifr_flags &= ~IFF_NOARP;
    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
      BX_PANIC(("SIOCSIFFLAGS: %s", strerror(errno)));
      close(sock);
      return;
    }
  }
  close(sock);
#endif

  fd = open (filename, O_RDWR);
  if (fd < 0) {
    BX_PANIC(("open failed on TAP %s: %s", netif, strerror(errno)));
    return;
  }

#if defined(__sun__) 
  char *ptr;       /* PD - ppa allocation ala qemu */
  char my_dev[10]; /* enough ... */
  int ppa=-1;
  struct strioctl strioc_ppa;

  my_dev[10-1]=0;
  strncpy(my_dev,netif,10); /* following ptr= does not work with const char* */
  if( *my_dev ) { /* find the ppa number X from string tapX */
    ptr = my_dev;
    while( *ptr && !isdigit((int)*ptr) ) ptr++;
    ppa = atoi(ptr);
  }
  /* Assign a new PPA and get its unit number. */
  strioc_ppa.ic_cmd = TUNNEWPPA;
  strioc_ppa.ic_timout = 0;
  strioc_ppa.ic_len = sizeof(ppa);
  strioc_ppa.ic_dp = (char *)&ppa;
  if ((ppa = ioctl (fd, I_STR, &strioc_ppa)) < 0)
    BX_PANIC(("Can't assign new interface tap%d !",ppa));
#endif

  /* set O_ASYNC flag so that we can poll with read() */
  if ((flags = fcntl(fd, F_GETFL)) < 0) {
    BX_PANIC(("getflags on tap device: %s", strerror(errno)));
  }
  flags |= O_NONBLOCK;
  if (fcntl(fd, F_SETFL, flags) < 0) {
    BX_PANIC(("set tap device flags: %s", strerror(errno)));
  }

  BX_INFO(("tap network drive: opened %s device", netif));

  /* Execute the configuration script */
  char intname[IFNAMSIZ];
  strcpy(intname,netif);
  if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0))
  {
    if (execute_script(this->netdev, script, intname) < 0)
      BX_ERROR(("execute script '%s' on %s failed", script, intname));
  }

  // Start the rx poll
  this->rx_timer_index =
    bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
                                1, 1, "eth_tap"); // continuous, active
  this->rxh   = rxh;
  memcpy(&guest_macaddr[0], macaddr, 6);
#if BX_ETH_TAP_LOGGING
  // eventually Bryce wants txlog to dump in pcap format so that
  // tcpdump -r FILE can read it and interpret packets.
  txlog = fopen("ne2k-tx.log", "wb");
  if (!txlog) BX_PANIC(("open ne2k-tx.log failed"));
  txlog_txt = fopen("ne2k-txdump.txt", "wb");
  if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed"));
  fprintf(txlog_txt, "tap packetmover readable log file\n");
  fprintf(txlog_txt, "net IF = %s\n", netif);
  fprintf(txlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf(txlog_txt, "\n--\n");
  fflush(txlog_txt);

  rxlog = fopen("ne2k-rx.log", "wb");
  if (!rxlog) BX_PANIC(("open ne2k-rx.log failed"));
  rxlog_txt = fopen("ne2k-rxdump.txt", "wb");
  if (!rxlog_txt) BX_PANIC(("open ne2k-rxdump.txt failed"));
  fprintf(rxlog_txt, "tap packetmover readable log file\n");
  fprintf(rxlog_txt, "net IF = %s\n", netif);
  fprintf(rxlog_txt, "MAC address = ");
  for (int i=0; i<6; i++)
    fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
  fprintf(rxlog_txt, "\n--\n");
  fflush(rxlog_txt);

#endif
}
示例#22
0
/*
  Configure node_t myself and set up the local sockets (listen only)
*/
static bool setup_myself(void) {
    config_t *cfg;
    subnet_t *subnet;
    char *name, *hostname, *mode, *afname, *cipher, *digest, *type;
    char *fname = NULL;
    char *address = NULL;
    char *proxy = NULL;
    char *space;
    char *envp[5] = {NULL};
    struct addrinfo *ai, *aip, hint = {0};
    bool choice;
    int i, err;
    int replaywin_int;
    bool port_specified = false;

    myself = new_node();
    myself->connection = new_connection();

    myself->hostname = xstrdup("MYSELF");
    myself->connection->hostname = xstrdup("MYSELF");

    myself->connection->options = 0;
    myself->connection->protocol_version = PROT_CURRENT;

    if(!(name = get_name())) {
        logger(LOG_ERR, "Name for tinc daemon required!");
        return false;
    }

    /* Read tinc.conf and our own host config file */

    myself->name = name;
    myself->connection->name = xstrdup(name);
    xasprintf(&fname, "%s/hosts/%s", confbase, name);
    read_config_options(config_tree, name);
    read_config_file(config_tree, fname);
    free(fname);

    if(!read_rsa_private_key())
        return false;

    if(!get_config_string(lookup_config(config_tree, "Port"), &myport))
        myport = xstrdup("655");
    else
        port_specified = true;

    /* Ensure myport is numeric */

    if(!atoi(myport)) {
        struct addrinfo *ai = str2addrinfo("localhost", myport, SOCK_DGRAM);
        sockaddr_t sa;
        if(!ai || !ai->ai_addr)
            return false;
        free(myport);
        memcpy(&sa, ai->ai_addr, ai->ai_addrlen);
        sockaddr2str(&sa, NULL, &myport);
    }

    get_config_string(lookup_config(config_tree, "Proxy"), &proxy);
    if(proxy) {
        if((space = strchr(proxy, ' ')))
            *space++ = 0;

        if(!strcasecmp(proxy, "none")) {
            proxytype = PROXY_NONE;
        } else if(!strcasecmp(proxy, "socks4")) {
            proxytype = PROXY_SOCKS4;
        } else if(!strcasecmp(proxy, "socks4a")) {
            proxytype = PROXY_SOCKS4A;
        } else if(!strcasecmp(proxy, "socks5")) {
            proxytype = PROXY_SOCKS5;
        } else if(!strcasecmp(proxy, "http")) {
            proxytype = PROXY_HTTP;
        } else if(!strcasecmp(proxy, "exec")) {
            proxytype = PROXY_EXEC;
        } else {
            logger(LOG_ERR, "Unknown proxy type %s!", proxy);
            return false;
        }

        switch(proxytype) {
        case PROXY_NONE:
        default:
            break;

        case PROXY_EXEC:
            if(!space || !*space) {
                logger(LOG_ERR, "Argument expected for proxy type exec!");
                return false;
            }
            proxyhost =  xstrdup(space);
            break;

        case PROXY_SOCKS4:
        case PROXY_SOCKS4A:
        case PROXY_SOCKS5:
        case PROXY_HTTP:
            proxyhost = space;
            if(space && (space = strchr(space, ' ')))
                *space++ = 0, proxyport = space;
            if(space && (space = strchr(space, ' ')))
                *space++ = 0, proxyuser = space;
            if(space && (space = strchr(space, ' ')))
                *space++ = 0, proxypass = space;
            if(!proxyhost || !*proxyhost || !proxyport || !*proxyport) {
                logger(LOG_ERR, "Host and port argument expected for proxy!");
                return false;
            }
            proxyhost = xstrdup(proxyhost);
            proxyport = xstrdup(proxyport);
            if(proxyuser && *proxyuser)
                proxyuser = xstrdup(proxyuser);
            if(proxypass && *proxypass)
                proxypass = xstrdup(proxypass);
            break;
        }

        free(proxy);
    }

    /* Read in all the subnets specified in the host configuration file */

    cfg = lookup_config(config_tree, "Subnet");

    while(cfg) {
        if(!get_config_subnet(cfg, &subnet))
            return false;

        subnet_add(myself, subnet);

        cfg = lookup_config_next(config_tree, cfg);
    }

    /* Check some options */

    if(get_config_bool(lookup_config(config_tree, "IndirectData"), &choice) && choice)
        myself->options |= OPTION_INDIRECT;

    if(get_config_bool(lookup_config(config_tree, "TCPOnly"), &choice) && choice)
        myself->options |= OPTION_TCPONLY;

    if(myself->options & OPTION_TCPONLY)
        myself->options |= OPTION_INDIRECT;

    get_config_bool(lookup_config(config_tree, "DirectOnly"), &directonly);
    get_config_bool(lookup_config(config_tree, "StrictSubnets"), &strictsubnets);
    get_config_bool(lookup_config(config_tree, "TunnelServer"), &tunnelserver);
    get_config_bool(lookup_config(config_tree, "LocalDiscovery"), &localdiscovery);
    strictsubnets |= tunnelserver;

    if(get_config_string(lookup_config(config_tree, "Mode"), &mode)) {
        if(!strcasecmp(mode, "router"))
            routing_mode = RMODE_ROUTER;
        else if(!strcasecmp(mode, "switch"))
            routing_mode = RMODE_SWITCH;
        else if(!strcasecmp(mode, "hub"))
            routing_mode = RMODE_HUB;
        else {
            logger(LOG_ERR, "Invalid routing mode!");
            return false;
        }
        free(mode);
    }

    if(get_config_string(lookup_config(config_tree, "Forwarding"), &mode)) {
        if(!strcasecmp(mode, "off"))
            forwarding_mode = FMODE_OFF;
        else if(!strcasecmp(mode, "internal"))
            forwarding_mode = FMODE_INTERNAL;
        else if(!strcasecmp(mode, "kernel"))
            forwarding_mode = FMODE_KERNEL;
        else {
            logger(LOG_ERR, "Invalid forwarding mode!");
            return false;
        }
        free(mode);
    }

    choice = true;
    get_config_bool(lookup_config(config_tree, "PMTUDiscovery"), &choice);
    if(choice)
        myself->options |= OPTION_PMTU_DISCOVERY;

    choice = true;
    get_config_bool(lookup_config(config_tree, "ClampMSS"), &choice);
    if(choice)
        myself->options |= OPTION_CLAMP_MSS;

    get_config_bool(lookup_config(config_tree, "PriorityInheritance"), &priorityinheritance);
    get_config_bool(lookup_config(config_tree, "DecrementTTL"), &decrement_ttl);
    if(get_config_string(lookup_config(config_tree, "Broadcast"), &mode)) {
        if(!strcasecmp(mode, "no"))
            broadcast_mode = BMODE_NONE;
        else if(!strcasecmp(mode, "yes") || !strcasecmp(mode, "mst"))
            broadcast_mode = BMODE_MST;
        else if(!strcasecmp(mode, "direct"))
            broadcast_mode = BMODE_DIRECT;
        else {
            logger(LOG_ERR, "Invalid broadcast mode!");
            return false;
        }
        free(mode);
    }

#if !defined(SOL_IP) || !defined(IP_TOS)
    if(priorityinheritance)
        logger(LOG_WARNING, "%s not supported on this platform", "PriorityInheritance");
#endif

    if(!get_config_int(lookup_config(config_tree, "MACExpire"), &macexpire))
        macexpire = 600;

    if(get_config_int(lookup_config(config_tree, "MaxTimeout"), &maxtimeout)) {
        if(maxtimeout <= 0) {
            logger(LOG_ERR, "Bogus maximum timeout!");
            return false;
        }
    } else
        maxtimeout = 900;

    if(get_config_int(lookup_config(config_tree, "UDPRcvBuf"), &udp_rcvbuf)) {
        if(udp_rcvbuf <= 0) {
            logger(LOG_ERR, "UDPRcvBuf cannot be negative!");
            return false;
        }
    }

    if(get_config_int(lookup_config(config_tree, "UDPSndBuf"), &udp_sndbuf)) {
        if(udp_sndbuf <= 0) {
            logger(LOG_ERR, "UDPSndBuf cannot be negative!");
            return false;
        }
    }

    if(get_config_int(lookup_config(config_tree, "ReplayWindow"), &replaywin_int)) {
        if(replaywin_int < 0) {
            logger(LOG_ERR, "ReplayWindow cannot be negative!");
            return false;
        }
        replaywin = (unsigned)replaywin_int;
    }

    if(get_config_string(lookup_config(config_tree, "AddressFamily"), &afname)) {
        if(!strcasecmp(afname, "IPv4"))
            addressfamily = AF_INET;
        else if(!strcasecmp(afname, "IPv6"))
            addressfamily = AF_INET6;
        else if(!strcasecmp(afname, "any"))
            addressfamily = AF_UNSPEC;
        else {
            logger(LOG_ERR, "Invalid address family!");
            return false;
        }
        free(afname);
    }

    get_config_bool(lookup_config(config_tree, "Hostnames"), &hostnames);

    /* Generate packet encryption key */

    if(get_config_string
            (lookup_config(config_tree, "Cipher"), &cipher)) {
        if(!strcasecmp(cipher, "none")) {
            myself->incipher = NULL;
        } else {
            myself->incipher = EVP_get_cipherbyname(cipher);

            if(!myself->incipher) {
                logger(LOG_ERR, "Unrecognized cipher type!");
                return false;
            }
        }
    } else
        myself->incipher = EVP_bf_cbc();

    if(myself->incipher)
        myself->inkeylength = myself->incipher->key_len + myself->incipher->iv_len;
    else
        myself->inkeylength = 1;

    myself->connection->outcipher = EVP_bf_ofb();

    if(!get_config_int(lookup_config(config_tree, "KeyExpire"), &keylifetime))
        keylifetime = 3600;

    keyexpires = now + keylifetime;

    /* Check if we want to use message authentication codes... */

    if(get_config_string(lookup_config(config_tree, "Digest"), &digest)) {
        if(!strcasecmp(digest, "none")) {
            myself->indigest = NULL;
        } else {
            myself->indigest = EVP_get_digestbyname(digest);

            if(!myself->indigest) {
                logger(LOG_ERR, "Unrecognized digest type!");
                return false;
            }
        }
    } else
        myself->indigest = EVP_sha1();

    myself->connection->outdigest = EVP_sha1();

    if(get_config_int(lookup_config(config_tree, "MACLength"), &myself->inmaclength)) {
        if(myself->indigest) {
            if(myself->inmaclength > myself->indigest->md_size) {
                logger(LOG_ERR, "MAC length exceeds size of digest!");
                return false;
            } else if(myself->inmaclength < 0) {
                logger(LOG_ERR, "Bogus MAC length!");
                return false;
            }
        }
    } else
        myself->inmaclength = 4;

    myself->connection->outmaclength = 0;

    /* Compression */

    if(get_config_int(lookup_config(config_tree, "Compression"), &myself->incompression)) {
        if(myself->incompression < 0 || myself->incompression > 11) {
            logger(LOG_ERR, "Bogus compression level!");
            return false;
        }
    } else
        myself->incompression = 0;

    myself->connection->outcompression = 0;

    /* Done */

    myself->nexthop = myself;
    myself->via = myself;
    myself->status.reachable = true;
    node_add(myself);

    graph();

    if(strictsubnets)
        load_all_subnets();

    /* Open device */

    devops = os_devops;

    if(get_config_string(lookup_config(config_tree, "DeviceType"), &type)) {
        if(!strcasecmp(type, "dummy"))
            devops = dummy_devops;
        else if(!strcasecmp(type, "raw_socket"))
            devops = raw_socket_devops;
        else if(!strcasecmp(type, "multicast"))
            devops = multicast_devops;
#ifdef ENABLE_UML
        else if(!strcasecmp(type, "uml"))
            devops = uml_devops;
#endif
#ifdef ENABLE_VDE
        else if(!strcasecmp(type, "vde"))
            devops = vde_devops;
#endif
    }

    if(!devops.setup())
        return false;

    /* Run tinc-up script to further initialize the tap interface */
    xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
    xasprintf(&envp[1], "DEVICE=%s", device ? : "");
    xasprintf(&envp[2], "INTERFACE=%s", iface ? : "");
    xasprintf(&envp[3], "NAME=%s", myself->name);

    execute_script("tinc-up", envp);

    for(i = 0; i < 4; i++)
        free(envp[i]);

    /* Run subnet-up scripts for our own subnets */

    subnet_update(myself, NULL, true);

    /* Open sockets */

    if(!do_detach && getenv("LISTEN_FDS")) {
        sockaddr_t sa;
        socklen_t salen;

        listen_sockets = atoi(getenv("LISTEN_FDS"));
#ifdef HAVE_UNSETENV
        unsetenv("LISTEN_FDS");
#endif

        if(listen_sockets > MAXSOCKETS) {
            logger(LOG_ERR, "Too many listening sockets");
            return false;
        }

        for(i = 0; i < listen_sockets; i++) {
            salen = sizeof sa;
            if(getsockname(i + 3, &sa.sa, &salen) < 0) {
                logger(LOG_ERR, "Could not get address of listen fd %d: %s", i + 3, sockstrerror(errno));
                return false;
            }

            listen_socket[i].tcp = i + 3;

#ifdef FD_CLOEXEC
            fcntl(i + 3, F_SETFD, FD_CLOEXEC);
#endif

            listen_socket[i].udp = setup_vpn_in_socket(&sa);
            if(listen_socket[i].udp < 0)
                return false;

            ifdebug(CONNECTIONS) {
                hostname = sockaddr2hostname(&sa);
                logger(LOG_NOTICE, "Listening on %s", hostname);
                free(hostname);
            }

            memcpy(&listen_socket[i].sa, &sa, salen);
        }
    } else {