예제 #1
0
void
end_session(struct session *s)
{
	int err;

	logmsg(LOG_INFO, "#%d ending session", s->id);

	/* Flush output buffers. */
	if (s->client_bufev && s->client_fd != -1)
		evbuffer_write(s->client_bufev->output, s->client_fd);
	if (s->server_bufev && s->server_fd != -1)
		evbuffer_write(s->server_bufev->output, s->server_fd);

	if (s->client_fd != -1)
		close(s->client_fd);
	if (s->server_fd != -1)
		close(s->server_fd);

	if (s->client_bufev)
		bufferevent_free(s->client_bufev);
	if (s->server_bufev)
		bufferevent_free(s->server_bufev);

	/* Remove rulesets by commiting empty ones. */
	err = 0;
	if (prepare_commit(s->id) == -1)
		err = errno;
	else if (do_commit() == -1) {
		err = errno;
		do_rollback();
	}
	if (err)
		logmsg(LOG_ERR, "#%d pf rule removal failed: %s", s->id,
		    strerror(err));

	LIST_REMOVE(s, entry);
	free(s);
	session_count--;
}
예제 #2
0
int
allow_data_connection(struct session *s)
{
	struct sockaddr *client_sa, *orig_sa, *proxy_sa, *server_sa;
	int prepared = 0;

	/*
	 * The pf rules below do quite some NAT rewriting, to keep up
	 * appearances.  Points to keep in mind:
	 * 1)  The client must think it's talking to the real server,
	 *     for both control and data connections.  Transparently.
	 * 2)  The server must think that the proxy is the client.
	 * 3)  Source and destination ports are rewritten to minimize
	 *     port collisions, to aid security (some systems pick weak
	 *     ports) or to satisfy RFC requirements (source port 20).
	 */
	
	/* Cast this once, to make code below it more readable. */
	client_sa = sstosa(&s->client_ss);
	server_sa = sstosa(&s->server_ss);
	proxy_sa = sstosa(&s->proxy_ss);
	if (fixed_server)
		/* Fixed server: data connections must appear to come
		   from / go to the original server, not the fixed one. */
		orig_sa = sstosa(&s->orig_server_ss);
	else
		/* Server not fixed: orig_server == server. */
		orig_sa = sstosa(&s->server_ss);

	/* Passive modes. */
	if (s->cmd == CMD_PASV || s->cmd == CMD_EPSV) {
		s->port = parse_port(s->cmd);
		if (s->port < MIN_PORT) {
			logmsg(LOG_CRIT, "#%d bad port in '%s'", s->id,
			    linebuf);
			return (0);
		}
		s->proxy_port = pick_proxy_port();
		logmsg(LOG_INFO, "#%d passive: client to server port %d"
		    " via port %d", s->id, s->port, s->proxy_port);

		if (prepare_commit(s->id) == -1)
			goto fail;
		prepared = 1;

		proxy_reply(s->cmd, orig_sa, s->proxy_port);
		logmsg(LOG_DEBUG, "#%d proxy: %s", s->id, linebuf);

		/* pass in from $client to $orig_server port $proxy_port
		    rdr-to $server port $port */
		if (add_rdr(s->id, client_sa, s->client_rd, orig_sa,
		    s->proxy_port, server_sa, s->port, getrtable()) == -1)
			goto fail;

		/* pass out from $client to $server port $port nat-to $proxy */
		if (add_nat(s->id, client_sa, getrtable(), server_sa,
		    s->port, proxy_sa, PF_NAT_PROXY_PORT_LOW,
		    PF_NAT_PROXY_PORT_HIGH) == -1)
			goto fail;
	}

	/* Active modes. */
	if (s->cmd == CMD_PORT || s->cmd == CMD_EPRT) {
		logmsg(LOG_INFO, "#%d active: server to client port %d"
		    " via port %d", s->id, s->port, s->proxy_port);

		if (prepare_commit(s->id) == -1)
			goto fail;
		prepared = 1;

		/* pass in from $server to $proxy port $proxy_port
		    rdr-to $client port $port */
		if (add_rdr(s->id, server_sa, getrtable(), proxy_sa,
		    s->proxy_port, client_sa, s->port, s->client_rd) == -1)
			goto fail;

		/* pass out from $server to $client port $port
		    nat-to $orig_server port $natport */
		if (rfc_mode && s->cmd == CMD_PORT) {
			/* Rewrite sourceport to RFC mandated 20. */
			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
			    s->port, orig_sa, 20, 20) == -1)
				goto fail;
		} else {
			/* Let pf pick a source port from the standard range. */
			if (add_nat(s->id, server_sa, s->client_rd, client_sa,
			    s->port, orig_sa, PF_NAT_PROXY_PORT_LOW,
			    PF_NAT_PROXY_PORT_HIGH) == -1)
			    	goto fail;
		}
	}

	/* Commit rules if they were prepared. */
	if (prepared && (do_commit() == -1)) {
		if (errno != EBUSY)
			goto fail;
		/* One more try if busy. */
		usleep(5000);
		if (do_commit() == -1)
			goto fail;
	}

	s->cmd = CMD_NONE;
	s->port = 0;

	return (1);

 fail:
	logmsg(LOG_CRIT, "#%d pf operation failed: %s", s->id, strerror(errno));
	if (prepared)
		do_rollback();
	return (0);
}
예제 #3
0
파일: ndbsql.cpp 프로젝트: A-eolus/mysql
int main(int argc, const char** argv)
{
  ndb_init();
  const char* usage = "Usage: ndbsql [-h] [-d dsn] [-f file] [stmt]\n-h help\n-d <database name or connect string>\n-f <file name> batch mode\nstmt single SQL statement\n";
  const char* dsn = "TEST_DB";
  bool helpFlg = false, batchMode = false;
  const char* fileName = 0;
  FILE* inputFile = stdin;
  const char* singleStmt = 0;

  s_readBuf = (char*)malloc(s_bufSize);
  while (++argv, --argc > 0) {
    const char* arg = argv[0];
    if (arg[0] != '-')
      break;
    if (strcmp(arg, "-d") == 0) {
      if (++argv, --argc > 0) {
        dsn = argv[0];
        continue;
      }
    }
    if (strcmp(arg, "-h") == 0) {
      helpFlg = true;
      continue;
    }
    if (strcmp(arg, "-f") == 0) {
      if (++argv, --argc > 0) {
	fileName = argv[0];
	continue;
      }
    }
    ndbout << usage;
    return 1;
  }
  if (helpFlg) {
    ndbout << usage << "\n";
    print_help();
    return 0;
  }
  if (fileName != 0) {
    if (argc > 0) {
      ndbout << usage;
      return 1;
    }
    if ((inputFile = fopen(fileName, "r")) == 0) {
      ndbout << "Could not read file " << fileName << ": " << strerror(errno) << endl;
      return 1;
    }
    batchMode = true;
  }
  if (argc > 0) {
    singleStmt = argv[0];
    batchMode = true;
  }
  if (! batchMode)
    ndbout << "NDB Cluster NDB SQL -- A simple SQL Command-line Interface\n\n";

  Con con(dsn);
  if (do_connect(con) < 0)
    return 1;
  if (! batchMode)
    ndbout << "Terminate SQL statements with a semi-colon ';'\n";

  char* line = 0;
  char* line2 = 0;
  char* line3 = 0;
  unsigned lineno = 0;
  bool has_semi;
  bool exit_on_error = false;
  int exit_code = 0;
  while (1) {
    free(line);
    line = 0;
    lineno = 0;

more_lines:
    free(line2);
    free(line3);
    line2 = line3 = 0;
    lineno++;
    has_semi = false;
    char prompt[20];
    if (lineno == 1)
      strcpy(prompt, "SQL> ");
    else
      sprintf(prompt, "%4d ", lineno);
    if (singleStmt != 0) {
      line = strdup(singleStmt);
      int n = strlen(line);
      while (n > 0 && isspace(line[n - 1])) {
        line[--n] = 0;
      }
      if (n > 0 && line[n - 1] == ';')
        line[n - 1] = 0;
      has_semi = true;  // regardless
    } else {
      const char *line1 = readline_gets(prompt, batchMode, inputFile); 
      if (line1 != 0) {
        if (line == 0)
          line = strdup(line1);
        else {
          line = (char*)realloc(line, strlen(line) + 1 + strlen(line1) + 1);
          strcat(line, "\n");
          strcat(line, line1);
        }
        if (batchMode)
          ndbout << prompt << line1 << endl;
      } else {
        if (! batchMode)
          ndbout << endl;
        if (line != 0)
          ndbout << "Ignored unterminated SQL statement" << endl;
        break;
      }
    }

    line2 = (char*)malloc(strlen(line) + 1);
    {
      char* p = line2;
      char* q = line;
      bool str = false;
      while (*q != 0) {
        if (*q == '\'') {
          str = !str;
          *p++ = *q++;
        } else if (!str && *q == '-' && *(q + 1) == '-') {
          while (*q != 0 && *q != '\n')
            q++;
        } else
          *p++ = *q++;
      }
      *p = 0;
      int n = strlen(line2);
      while (n > 0 && isspace(line2[n - 1]))
        line2[--n] = 0;
      if (n > 0 && line2[n - 1] == ';') {
        line2[--n] = 0;
        has_semi = true;
      }
    }
    line3 = strdup(line2);
    char* tok[10];
    int ntok = 0;
    tok[ntok] = strtok(line3, " ");
    while (tok[ntok] != 0) {
      ntok++;
      if (ntok == 10)
        break;
      tok[ntok] = strtok(0, " ");
    }
    if (ntok == 0)
      continue;

    if (!strcasecmp(tok[0], "help") || !strcmp(tok[0], "?")) {
      if (ntok != 2)
	print_help();
      else if (!strcasecmp(tok[1], "create"))
	print_help_create();
      else if (!strcasecmp(tok[1], "insert"))
	print_help_insert();
      else if (strcasecmp(tok[1], "select"))
	print_help_select();
      else if (!strcasecmp(tok[1], "delete"))
	print_help_update();
      else if (!strcasecmp(tok[1], "update"))
	print_help_update();
      else if (!strcasecmp(tok[1], "virtual"))
	print_help_virtual();
      else
	print_help();
      continue;
    }

    if (!strcasecmp(tok[0], "list")) {
      if (ntok == 2 && !strcasecmp(tok[1], "tables")) {
	free(line2);
	line2 = strdup("SELECT TABLE_NAME FROM ODBC$TABLES");
        has_semi = true;
      } else {
        ndbout << "Invalid list option - try help" << endl;
        continue;
      }
    }

    if (ntok == 1 && !strcasecmp(tok[0], "quit"))
      break;
    if (ntok == 1 && !strcasecmp(tok[0], "exit"))
      break;
    if (ntok == 1 && !strcasecmp(tok[0], "bye"))
      break;

    if (!strcasecmp(tok[0], "set")) {
      if (ntok == 1) {
	char* p;
	p = getenv("NDB_ODBC_TRACE");
	ndbout << "Trace level is " << (p ? atoi(p) : 0) << endl;
	int ret = get_autocommit(con);
	if (ret != -1)
	  ndbout << "Autocommit is " << (ret == SQL_AUTOCOMMIT_ON ? "on" : "off") << endl;
      } else if (ntok == 3 && !strcasecmp(tok[1], "trace")) {
	static char env[40];
	int n = tok[2] ? atoi(tok[2]) : 0;
	sprintf(env, "NDB_ODBC_TRACE=%d", n);
	putenv(env);
	ndbout << "Trace level set to " << n << endl;
      } else if (ntok == 3 && !strcasecmp(tok[1], "autocommit")) {
	if (tok[2] && !strcasecmp(tok[2], "on")) {
	  int ret = set_autocommit(con, SQL_AUTOCOMMIT_ON);
	  if (ret != -1)
	    ndbout << "Autocommit set to ON" << endl;
	} else if (tok[2] && !strcasecmp(tok[2], "off")) {
	  int ret = set_autocommit(con, SQL_AUTOCOMMIT_OFF);
	  if (ret != -1)
	    ndbout << "Autocommit set to OFF - transaction may time out" << endl;
	} else {
	  ndbout << "Invalid autocommit option - try help" << endl;
	}
      } else {
	ndbout << "Invalid set command - try help" << endl;
      }
      continue;
    }

    if (ntok >= 2 &&
        !strcasecmp(tok[0], "whenever") && !strcasecmp(tok[1], "sqlerror")) {
      if (ntok == 3 && !strcasecmp(tok[2], "exit"))
        exit_on_error = true;
      else if (ntok == 3 && !strcasecmp(tok[2], "continue"))
        exit_on_error = false;
      else {
        ndbout << "Invalid whenever clause - try help" << endl;
      }
      continue;
    }

    if (!strcasecmp(tok[0], "commit")) {
      if (ntok == 1) {
        if (do_commit(con) != -1)
          ndbout << "Commit done" << endl;
        else {
          exit_code = 1;
          if (exit_on_error) {
            ndbout << "Exit on error" << endl;
            break;
          }
        }
      } else {
        ndbout << "Invalid commit command - try help" << endl;
      }
      continue;
    }

    if (!strcasecmp(tok[0], "rollback")) {
      if (ntok == 1) {
        if (do_rollback(con) != -1)
          ndbout << "Rollback done" << endl;
        else {
          exit_code = 1;
          if (exit_on_error) {
            ndbout << "Exit on error" << endl;
            break;
          }
        }
      } else {
        ndbout << "Invalid commit command - try help" << endl;
      }
      continue;
    }

    if (! has_semi)
      goto more_lines;
    if (do_stmt(con, line2) != 0) {
      exit_code = 1;
      if (exit_on_error) {
        ndbout << "Exit on error" << endl;
        break;
      }
    }
    if (singleStmt)
      break;
  }
  do_disconnect(con);
  return exit_code;
}