Пример #1
0
/*************************************************
* CTR-BE Encryption/Decryption                   *
*************************************************/
void CTR_BE::write(const byte input[], u32bit length)
   {
   u32bit copied = std::min(BLOCK_SIZE - position, length);
   xor_buf(buffer + position, input, copied);
   send(buffer + position, copied);
   input += copied;
   length -= copied;
   position += copied;

   if(position == BLOCK_SIZE)
      increment_counter();

   while(length >= BLOCK_SIZE)
      {
      xor_buf(buffer, input, BLOCK_SIZE);
      send(buffer, BLOCK_SIZE);

      input += BLOCK_SIZE;
      length -= BLOCK_SIZE;
      increment_counter();
      }

   xor_buf(buffer + position, input, length);
   send(buffer + position, length);
   position += length;
   }
Пример #2
0
/* Internal function to return processed entropy from the PRNG */
int
random_yarrow_read(void *buf, int count)
{
	static int cur = 0;
	static int gate = 1;
	static uint8_t genval[KEYSIZE];
	size_t tomove;
	int i;
	int retval;

	/* Check for final read request */
	if (buf == NULL && count == 0)
		return (0);

	/* The reseed task must not be jumped on */
	mtx_lock(&random_reseed_mtx);

	if (gate) {
		generator_gate();
		random_state.outputblocks = 0;
		gate = 0;
	}
	if (count > 0 && (size_t)count >= BLOCKSIZE) {
		retval = 0;
		for (i = 0; i < count; i += BLOCKSIZE) {
			increment_counter();
			randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
			tomove = MIN(count - i, BLOCKSIZE);
			memcpy((char *)buf + i, genval, tomove);
			if (++random_state.outputblocks >= random_state.gengateinterval) {
				generator_gate();
				random_state.outputblocks = 0;
			}
			retval += (int)tomove;
			cur = 0;
		}
	}
	else {
		if (!cur) {
			increment_counter();
			randomdev_encrypt(&random_state.key, random_state.counter.byte, genval, BLOCKSIZE);
			memcpy(buf, genval, (size_t)count);
			cur = BLOCKSIZE - count;
			if (++random_state.outputblocks >= random_state.gengateinterval) {
				generator_gate();
				random_state.outputblocks = 0;
			}
			retval = count;
		}
		else {
			retval = MIN(cur, count);
			memcpy(buf, &genval[BLOCKSIZE - cur], (size_t)retval);
			cur -= retval;
		}
	}
	mtx_unlock(&random_reseed_mtx);
	return (retval);
}
Пример #3
0
/* Initialize a session-record.
 */
void init_session(t_session *session) {
#ifdef ENABLE_TOMAHAWK
	increment_counter(COUNTER_CLIENT);
#endif
	if ((session->client_id = new_client_id++) == MAX_CHILD_ID) {
		new_client_id = 0;
	}
	session->request_limit = true;
	session->force_quit = false;
	session->keep_alive = false;
	session->kept_alive = 0;

	session->last_host = NULL;
	session->request = NULL;
	session->buffer_size = 0;
	session->bytes_in_buffer = 0;

	clear_session(session);

	session->socket_open = false;
	session->via_trusted_proxy = false;
	session->flooding_timer = session->time;

#ifdef ENABLE_RPROXY
	session->rproxy_kept_alive = false;
#endif

#ifdef ENABLE_HTTP2
	session->use_http2 = false;
#endif
}
Пример #4
0
static void loop_creating_worker(void* context) {
  (void) context;

  do {
    uv_loop_t *loop;
    uv_signal_t signal;
    int r;

    loop = malloc(sizeof(*loop));
    ASSERT(loop != NULL);
    ASSERT(0 == uv_loop_init(loop));

    r = uv_signal_init(loop, &signal);
    ASSERT(r == 0);

    r = uv_signal_start(&signal, signal_unexpected_cb, SIGTERM);
    ASSERT(r == 0);

    uv_close((uv_handle_t*) &signal, NULL);

    r = uv_run(loop, UV_RUN_DEFAULT);
    ASSERT(r == 0);

    uv_loop_close(loop);
    free(loop);

    increment_counter(&loop_creation_counter);
  } while (!stop);
}
Пример #5
0
/* Validate URL
 */
bool validate_url(t_session *session) {
	if (valid_uri(session->uri, session->host->allow_dot_files)) {
		if (session->host->secure_url == false) {
			return true;
		} else if (strstr(session->request_uri, "%00") == NULL) {
			return true;
		} else {
			session->return_code = 403;
		}
	} else {
		session->return_code = (session->request_method == PUT) ? 403 : 404;
	}

	log_exploit_attempt(session, "invalid URL", NULL);
#ifdef ENABLE_TOMAHAWK
	increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
	if (session->config->monitor_enabled) {
		monitor_count_exploit(session);
		monitor_event("Invalid URL %s for %s", session->uri, session->host->hostname.item[0]);
	}
#endif

	session->error_cause = ec_INVALID_URL;

	return false;
}
Пример #6
0
/* Prevent Cross-site Request Forgery
 */
int prevent_csrf(t_session *session) {
	char *referer, *slash;
	int i, n;

	if (strcmp(session->method, "POST") != 0) {
		return 0;
	}

	if ((referer = get_http_header("Referer:", session->http_headers)) == NULL) {
		return 0;
	}

	if (strncmp(referer, "http://", 7) == 0) {
		referer += 7;
	} else if (strncmp(referer, "https://", 8) == 0) {
		referer += 8;
	} else {
		session->cookie = NULL;

		log_error(session, "invalid referer while checking for CSRF");

		return 1;
	}

	if ((slash = strchr(referer, '/')) != NULL) {
		n = slash - referer;
	} else {
		n = strlen(referer);
	}

	for (i = 0; i < session->host->hostname.size; i++) {
		if (strncasecmp(referer, *(session->host->hostname.item + i), n) == 0) {
			return 0;
		}
	}

	session->cookie = NULL;

	if (session->body != NULL) {
		log_exploit_attempt(session, "CSRF", session->body);
#ifdef ENABLE_TOMAHAWK
		increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
		if (session->config->monitor_enabled) {
			monitor_counter_exploit_attempt(session);
		}
#endif
	} else {
		log_error(session, "CSRF attempt detected with no request body");
	}

#ifdef ENABLE_MONITOR
	if (session->config->monitor_enabled) {
		monitor_counter_exploit_attempt(session);
	}
#endif

	return 1;
}
Пример #7
0
void Blake2b::add_data(const byte input[], size_t length)
   {
   if(!input || length == 0)
      {
      return;
      }

   byte* const buffer = m_buffer.data();

   while(length > 0)
      {
      size_t fill = BLAKE2B_BLOCKBYTES - m_buflen;

      if(length <= fill)
         {
         std::memcpy(buffer + m_buflen, input, length);
         m_buflen += length;
         return;
         }

      std::memcpy(buffer + m_buflen, input, fill);
      increment_counter(BLAKE2B_BLOCKBYTES);
      compress();

      m_buflen = 0;
      input += fill;
      length -= fill;
      }
   }
Пример #8
0
int handle_connection_not_allowed(t_session *session, int connections) {
	switch (connections) {
		case ca_TOOMUCH_PERIP:
			log_system(session, "Maximum number of connections for IP address reached");
			if ((session->config->ban_on_max_per_ip > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				log_system(session, "Client banned because of too many simultaneous connections");
				ban_ip(&(session->ip_address), session->config->ban_on_max_per_ip, session->config->kick_on_ban);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			return 444;
		case ca_TOOMUCH_TOTAL:
			log_system(session, "Maximum number of total connections reached");
			return 503;
		case ca_BANNED:
			if (session->config->reban_during_ban && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				reban_ip(&(session->ip_address));
			}
#ifdef ENABLE_TOMAHAWK
			increment_counter(COUNTER_DENY);
#endif
			return 444;
	}

	return 500;
}
Пример #9
0
static void loop_creating_worker(void* context) {
  (void) context;

  do {
    uv_loop_t* loop;
    uv_signal_t signal;
    int r;

    loop = uv_loop_new();
    ASSERT(loop != NULL);

    r = uv_signal_init(loop, &signal);
    ASSERT(r == 0);

    r = uv_signal_start(&signal, signal_unexpected_cb, SIGTERM);
    ASSERT(r == 0);

    uv_close((uv_handle_t*) &signal, NULL);

    r = uv_run(loop);
    ASSERT(r == 0);

    uv_loop_delete(loop);

    increment_counter(&loop_creation_counter);
  } while (!stop);
}
Пример #10
0
static void set_hf_send_packet(int fd_out, int fd_in, unsigned char buffer[], unsigned char len, unsigned char *seq, unsigned char type, unsigned char response[], int *response_length) {
    set_packet_header(buffer, len, *seq, type);

    crc_packet(tabel, buffer, len);

    send_packet(fd_out, fd_in, buffer, len + 2, response, response_length);

    increment_counter(seq);
}
Пример #11
0
extern "C" void kokkosp_begin_parallel_reduce(const char* name, const uint32_t devID, uint64_t* kID) {
	*kID = uniqID++;

	if( (NULL == name) || (strcmp("", name) == 0) ) {
		fprintf(stderr, "Error: kernel is empty\n");
		exit(-1);
	}

	increment_counter(name, PARALLEL_REDUCE);
}
Пример #12
0
static void log_sqli_attempt(t_session *session, char *str) {
	log_exploit_attempt(session, "SQLi", str);
#ifdef ENABLE_TOMAHAWK
	increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
	if (session->config->monitor_enabled) {
		monitor_count_exploit_attempt(session);
		monitor_event("SQLi attempt for %s%s", session->host->hostname.item[0], session->uri);
	}
#endif
}
Пример #13
0
static int prevent_xss_str(t_session *session, char *input) {
	int result = 0;
	short low, high;
	char *str, value;
	char tag[22];

	str = input;

	while (*str != '\0') {
		if ((value = *str) == '%') {
			if ((high = hex_char_to_int(*(str + 1))) != -1) {
				if ((low = hex_char_to_int(*(str + 2))) != -1) {
					value = (char)(high<<4) + low;
					str += 2;
				}
			}
		}

		if (value == '<') {
			str++;
			strncpy(tag, str, 21);
			tag[21] = '\0';
			url_decode(tag);
			strlower(tag);

			if ((memcmp(tag, "script", 6) == 0) && ((tag[6] == ' ') || (tag[6] == '>'))) {
				log_exploit_attempt(session, "XSS", input);
#ifdef ENABLE_TOMAHAWK
				increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_exploit_attempt(session);
					monitor_event("XSS attempt for %s%s", session->host->hostname.item[0], session->uri);
				}
#endif

				if (session->host->prevent_xss == p_prevent) {
					*str = '_';
				}

				result = 1;

				break;
			}
		}

		str++;
	}

	return result;
}
Пример #14
0
static void
generator_gate(void)
{
	u_int i;
	uint8_t temp[KEYSIZE];

	for (i = 0; i < KEYSIZE; i += BLOCKSIZE) {
		increment_counter();
		randomdev_encrypt(&random_state.key, random_state.counter.byte, temp + i, BLOCKSIZE);
	}

	randomdev_encrypt_init(&random_state.key, temp);
	memset((void *)temp, 0, KEYSIZE);
}
Пример #15
0
/* Prevent SQL injection
 */
static int prevent_sqli_str(t_session *session, char *str, int length) {
	char *data, *c;
	t_sqli_pattern *pattern;
	int result = 0;

	if ((str == NULL) || (length <= 0)) {
		return 0;
	}

	if ((data = (char*)malloc(length + 1)) == NULL) {
		return -1;
	}
	memcpy(data, str, length);
	data[length] = '\0';
	url_decode(data);

	c = data;
	while (*c != '\0') {
		if (*c == '+') {
			*c = ' ';
		}
		c++;
	}

	pattern = sqli_patterns;
	while (pattern != NULL) {
		if (regexec(&(pattern->regex), data, 0, NULL, 0) != REG_NOMATCH) {
			log_exploit_attempt(session, "SQLi", str);
#ifdef ENABLE_TOMAHAWK
			increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_exploit(session);
				monitor_event("SQLi attempt for %s", session->file_on_disk);
			}
#endif

			result = 1;
			break;
		}

		pattern = pattern->next;
	}

	free(data);

	return result;
}
Пример #16
0
/* Prevent cross-site scripting.
 */
int prevent_xss(t_session *session) {
	int result = 0;
	bool logged = false;
	short low, high;
	char *str, value;

	if ((str = session->vars) == NULL) {
		return 0;
	}

	while (*str != '\0') {
		if ((value = *str) == '%') {
			if ((high = hex_char_to_int(*(str + 1))) != -1) {
				if ((low = hex_char_to_int(*(str + 2))) != -1) {
					value = (char)(high<<4) + low;
				}
			}
		}

		if ((value == '\"') || (value == '<') || (value == '>') || (value == '\'')) {
			if (logged == false) {
				log_exploit_attempt(session, "XSS", session->vars);
#ifdef ENABLE_TOMAHAWK
				increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_exploit(session);
					monitor_event("XSS attempt for %s", session->file_on_disk);
				}
#endif
				logged = true;
			}

			*str = '_';
			result = 1;
		}
		str++;
	}

	return result;
}
Пример #17
0
void Blake2b::final_result(byte output[])
   {
   if(!output)
      {
      return;
      }

   byte* const buffer = m_buffer.data();
   const u64bit* const H = static_cast<const u64bit*>(m_H.data());
   u16bit outlen = static_cast<u16bit>(output_length());

   std::memset(buffer + m_buflen, 0, BLAKE2B_BLOCKBYTES - m_buflen);
   increment_counter(m_buflen);
   compress(true);

   for (u16bit i = 0; i < outlen; i++)
      {
      output[i] = (H[i >> 3] >> (8 * (i & 7))) & 0xFF;
      }

   clear();
   }
void print_Multiarray_T_tol (const struct Multiarray_T*const a, const Real tol)
{
	const int order               = a->order;
	const ptrdiff_t*const extents = a->extents;

	print_Multiarray_extents(order,extents);

	if (order == 1) {
		struct Vector_T* a_V = constructor_move_Vector_T_T(extents[0],false,a->data); // destructed
		print_Vector_T_tol(a_V,tol);
		destructor_Vector_T(a_V);
	} else if (order == 2) {
		struct Matrix_T* a_M = constructor_move_Matrix_T_T(a->layout,extents[0],extents[1],false,a->data); // destructed
		print_Matrix_T_tol(a_M,tol);
		destructor_Matrix_T(a_M);
	} else if (order > 2) {
		struct Matrix_T* a_M = constructor_move_Matrix_T_T(a->layout,extents[0],extents[1],false,NULL); // destructed

		const ptrdiff_t size_tail = compute_size(order-2,&extents[2]);

		ptrdiff_t counter[order-2];
		for (ptrdiff_t i = 0; i < order-2; ++i)
			counter[i] = 0;

		for (ptrdiff_t i = 0; i < size_tail; ++i) {
			print_Multiarray_counter(order,counter);

			const ptrdiff_t ind_M = compute_index_sub_matrix(order,extents,counter);
			a_M->data = &a->data[ind_M];
			print_Matrix_T_tol(a_M,tol);

			increment_counter(order,extents,counter);
		}
		destructor_Matrix_T(a_M);
	} else {
		EXIT_ERROR("Unsupported: %d\n",order);
	}
	printf("\n");
}
Пример #19
0
void increment (void)
{
  int got_throw = 0;

  /*
   * At most one thread at a time can execute Scheme code.
   * So call Scheme in a critical section.
   */

  pthread_mutex_lock (&mut);

  /* call Scheme to increment counter */

  ___ON_THROW(increment_counter (counter), got_throw=1);

  pthread_mutex_unlock (&mut);

  if (got_throw)
    {
      printf ("thread %p is terminating\n", pthread_self ());
      pthread_exit (NULL); /* exit if Scheme threw an exception */
    }
}
Пример #20
0
/* Serve the client that connected to the webserver
 */
static int serve_client(t_session *session) {
	int result, length, auth_result;
	char *qmark, chr, *header;
	t_host *host_record;
	t_access access;
	t_deny_body *deny_body;
	t_req_method request_method;
	t_ip_addr ip_addr;
#ifdef ENABLE_XSLT
	char *xslt_file;
#endif
#ifdef ENABLE_TOOLKIT
	int i;
	t_toolkit_options toolkit_options;
#endif
#ifdef ENABLE_RPROXY
	t_rproxy *rproxy;
#endif

#ifdef ENABLE_DEBUG
	session->current_task = "fetch & parse request";
#endif

	if ((result = fetch_request(session)) != 200) {
		session->request_method = GET;
		return result;
	} else if ((result = parse_request(session, session->header_length + session->content_length)) != 200) {
		session->request_method = GET;
		return result;
	}

#ifdef ENABLE_DEBUG
	session->current_task = "serve client";
#endif

	session->time = time(NULL);

	/* Hide reverse proxies
	 */
	if (in_iplist(session->config->hide_proxy, &(session->ip_address))) {
		if (last_forwarded_ip(session->http_headers, &ip_addr) == 0) {
			if (reposition_client(session, &ip_addr) != -1) {
				copy_ip(&(session->ip_address), &ip_addr);
			}
		}
	}

	/* SSH tunneling
	 */
#ifdef ENABLE_RPROXY
	if (session->request_method == CONNECT) {
		if (in_iplist(session->config->tunnel_ssh, &(session->ip_address)) == false) {
			return 405;
		}

#ifdef ENABLE_SSL
		if (session->binding->use_ssl) {
			return 405;
		}
#endif

		if (strcmp(session->request_uri, "localhost:22") != 0) {
			if (strcmp(session->request_uri, "127.0.0.1:22") != 0) {
				if (strcmp(session->request_uri, "::1.22") != 0) {
					return 403;
				}
			}
		}

		log_system(session, "SSH tunnel requested");
		if (tunnel_ssh_connection(session->client_socket) != 0) {
			log_system(session, "SSH tunnel failed");
		} else {
			log_system(session, "SSH tunnel terminated");
		}

		session->keep_alive = false;

		return 200;
	}
#endif

	/* Find host record
	 */
	if (session->hostname != NULL) {
		if (remove_port_from_hostname(session) == -1) {
			log_error(session, "error removing port from hostname");
			return 500;
		}

		if ((host_record = get_hostrecord(session->config->first_host, session->hostname, session->binding)) != NULL) {
			session->host = host_record;
#ifdef ENABLE_TOMAHAWK
			session->last_host = host_record;
#endif
		}
	}
	session->host->access_time = session->time;

#ifdef ENABLE_SSL
	/* SSL client authentication
	 */
	if (session->binding->use_ssl) {
		if ((session->host->ca_certificate != NULL) && (ssl_has_peer_cert(&(session->ssl_context)) == false)) {
			log_error(session, "Missing client SSL certificate");
			return 440;
		}
	}
#endif

	/* Enforce usage of first hostname
	 */
	if (session->host->enforce_first_hostname && (session->hostname != NULL)) {
		if (**(session->host->hostname.item) != '*') {
			if (strcmp(session->hostname, *(session->host->hostname.item)) != 0) {
				session->cause_of_301 = enforce_first_hostname;
				return 301;
			}
		}
	}

	/* Enforce usage of SSL
	 */
#ifdef ENABLE_SSL
	if (session->host->require_ssl && (session->binding->use_ssl == false)) {
		if ((qmark = strchr(session->uri, '?')) != NULL) {
			*qmark = '\0';
			session->vars = qmark + 1;
			session->uri_len = strlen(session->uri);
		}
		session->cause_of_301 = require_ssl;
		return 301;
	}
#endif

	/* Deny matching bodies
	 */
	if (session->body != NULL) {
		chr = *(session->body + session->content_length);
		*(session->body + session->content_length) = '\0';

		deny_body = session->host->deny_body;
		while (deny_body != NULL) {
			if (strpcmp(session->body, &(deny_body->pattern)) == 0) {
				if ((session->config->ban_on_denied_body > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
					ban_ip(&(session->ip_address), session->config->ban_on_denied_body, session->config->kick_on_ban);
					log_system(session, "Client banned because of denied body");
#ifdef ENABLE_MONITOR
					if (session->config->monitor_enabled) {
						monitor_count_ban(session);
					}
#endif
				}

				log_exploit_attempt(session, "denied body", session->body);
#ifdef ENABLE_TOMAHAWK
				increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_exploit(session);
					monitor_event("Request body denied for %s", session->host->hostname.item[0]);
				}
#endif

				*(session->body + session->content_length) = chr;

				return 403;
			}
			deny_body = deny_body->next;
		}

		*(session->body + session->content_length) = chr;
	}

	/* Websocket
	 */
	if (session->request_method == GET) {
		if ((header = get_http_header("Connection:", session->http_headers)) != NULL) {
			if (strcasestr(header, "upgrade") != NULL) {
				if ((header = get_http_header("Upgrade:", session->http_headers)) != NULL) {
					if (strcasecmp(header, "websocket") == 0) {
						switch (access = allow_client(session)) {
							case deny:
								log_error(session, fb_accesslist);
								return 403;
							case allow:
								break;
							case pwd:
							case unspecified:
								if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
									return auth_result;
								}
						}

						session->keep_alive = false;
						if (forward_to_websocket(session) == -1) {
							return 500;
						}

						return 200;
					}
				}
			}
		}
	}

#ifdef ENABLE_RPROXY
	/* Reverse proxy
	 */
	rproxy = session->host->rproxy;
	while (rproxy != NULL) {
		if (rproxy_match(rproxy, session->request_uri)) {
			if (rproxy_loop_detected(session->http_headers)) {
				return 508;
			}

			if ((qmark = strchr(session->uri, '?')) != NULL) {
				*qmark = '\0';
				session->vars = qmark + 1;
			}

			if (validate_url(session) == false) {
				return -1;
			}

			if ((session->vars != NULL) && (session->host->secure_url)) {
				if (forbidden_chars_present(session->vars)) {
					log_error(session, "URL contains forbidden characters");
					return 403;
				}
			}

			if (duplicate_host(session) == false) {
				log_error(session, "duplicate_host() error");
				return 500;
			}

			if ((result = uri_to_path(session)) != 200) {
				return result;
			}

			if (session->host->ignore_dot_hiawatha == false) {
				if (load_user_config(session) == -1) {
					return 500;
				}
			}

			if ((result = copy_directory_settings(session)) != 200) {
				return result;
			}

			switch (access = allow_client(session)) {
				case deny:
					log_error(session, fb_accesslist);
					return 403;
				case allow:
					break;
				case pwd:
				case unspecified:
					if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
						return auth_result;
					}
			}

			/* Prevent SQL injection
			 */
			if (session->host->prevent_sqli) {
				result = prevent_sqli(session);
				if (result == 1) {
					session->error_cause = ec_SQL_INJECTION;
				}
				if (result != 0) {
					return -1;
				}
			}

			/* Prevent Cross-site Scripting
			 */
			if (session->host->prevent_xss != p_no) {
				if (prevent_xss(session) > 0) {
					if (session->host->prevent_xss == p_block) {
						session->error_cause = ec_XSS;
						return -1;
					}
				}
			}

			/* Prevent Cross-site Request Forgery
			 */
			if (session->host->prevent_csrf != p_no) {
				if (prevent_csrf(session) > 0) {
					if (session->host->prevent_csrf == p_block) {
						session->error_cause = ec_CSRF;
						return -1;
					}
				}
			}

			return proxy_request(session, rproxy);
		}

		rproxy = rproxy->next;
	}
#endif

	/* Actions based on request method
	 */
	switch (session->request_method) {
		case TRACE:
			if (session->binding->enable_trace == false) {
				return 501;
			}
			return handle_trace_request(session);
		case PUT:
		case DELETE:
			if ((session->binding->enable_alter == false) && (session->host->webdav_app == false)) {
				return 501;
			}
			break;
		case unknown:
			return 400;
		case unsupported:
			if (session->host->webdav_app == false) {
				return 501;
			}
			break;
		default:
			break;
	}

	if (duplicate_host(session) == false) {
		log_error(session, "duplicate_host() error");
		return 500;
	}

#ifdef ENABLE_TOOLKIT
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_root_config(session) == -1) {
			return 500;
		}
	}

	/* URL toolkit
	 */
	init_toolkit_options(&toolkit_options);
	toolkit_options.method = session->method;
	toolkit_options.website_root = session->host->website_root;
	toolkit_options.url_toolkit = session->config->url_toolkit;
	toolkit_options.allow_dot_files = session->host->allow_dot_files;
	toolkit_options.http_headers = session->http_headers;
#ifdef ENABLE_SSL
	toolkit_options.use_ssl = session->binding->use_ssl;
#endif

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		for (i = 0; i < session->host->toolkit_rules.size; i++) {
			if ((result = use_toolkit(session->uri, session->host->toolkit_rules.item[i], &toolkit_options)) == UT_ERROR) {
				return 500;
			}

			if ((toolkit_options.ban > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), toolkit_options.ban, session->config->kick_on_ban);
				log_system(session, "Client banned because of URL match in UrlToolkit rule");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
				return 403;
			}

			session->toolkit_fastcgi = toolkit_options.fastcgi_server;
			if (toolkit_options.new_url != NULL) {
				if (register_tempdata(&(session->tempdata), toolkit_options.new_url, tc_data) == -1) {
					free(toolkit_options.new_url);
					log_error(session, "error registering temporary data");
					return 500;
				}
				session->uri = toolkit_options.new_url;
			}

			if (result == UT_REDIRECT) {
				if ((session->location = strdup(toolkit_options.new_url)) == NULL) {
					return -1;
				}
				session->cause_of_301 = location;
				return 301;
			}

			if (result == UT_DENY_ACCESS) {
				log_error(session, "access denied via URL toolkit rule");
				return 403;
			}

			if (toolkit_options.expire > -1) {
				session->expires = toolkit_options.expire;
				session->caco_private = toolkit_options.caco_private;
			}
		}
	}
#endif

	/* Find GET data
	 */
	if ((qmark = strchr(session->uri, '?')) != NULL) {
		*qmark = '\0';
		session->vars = qmark + 1;
	}

	url_decode(session->uri);
	session->uri_len = strlen(session->uri);

	if ((session->vars != NULL) && (session->host->secure_url)) {
		if (forbidden_chars_present(session->vars)) {
			log_error(session, "URL contains forbidden characters");
			return 403;
		}
	}

	if (validate_url(session) == false) {
		return -1;
	}

	if ((result = uri_to_path(session)) != 200) {
		return result;
	}

	/* Load configfile from directories
	 */
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_config(session) == -1) {
			return 500;
		}
	}

	if ((result = copy_directory_settings(session)) != 200) {
		return result;
	}

	switch (access = allow_client(session)) {
		case deny:
			log_error(session, fb_accesslist);
			return 403;
		case allow:
			break;
		case pwd:
		case unspecified:
			if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
				return auth_result;
			}
	}

	switch (is_directory(session->file_on_disk)) {
		case error:
			return 500;
		case yes:
			session->uri_is_dir = true;
			break;
		case no:
			if (((session->request_method != PUT) || session->host->webdav_app) && (session->host->enable_path_info)) {
				if ((result = get_path_info(session)) != 200) {
					return result;
				}
			}
			break;
		case no_access:
			log_error(session, fb_filesystem);
			return 403;
		case not_found:
			if (session->request_method == DELETE) {
				return 404;
			}
	}

#ifdef ENABLE_TOOLKIT
	if ((session->toolkit_fastcgi == NULL) && session->uri_is_dir) {
#else
	if (session->uri_is_dir) {
#endif
		length = strlen(session->file_on_disk);
		if (*(session->file_on_disk + length - 1) == '/') {
			strcpy(session->file_on_disk + length, session->host->start_file);
		} else {
			return 301;
		}
	}

	if (get_target_extension(session) == -1) {
		log_error(session, "error getting extension");
		return 500;
	}

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		check_target_is_cgi(session);
	}

	/* Handle request based on request method
	 */
	request_method = session->request_method;
	if (session->host->webdav_app) {
		if ((request_method == PUT) || (request_method == DELETE)) {
			request_method = POST;
		}
	}

	switch (request_method) {
		case GET:
		case HEAD:
			if (session->cgi_type != no_cgi) {
				session->body = NULL;
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = send_file(session);
			}
			if (result == 404) {
#ifdef ENABLE_XSLT
				if ((session->host->show_index != NULL) && (session->uri[session->uri_len - 1] == '/')) {
					result = show_index(session);
				}
#endif
#ifdef ENABLE_MONITOR
			} else if (session->config->monitor_enabled) {
				if ((result == 200) && (session->host->monitor_host)) {
					unlink(session->file_on_disk);
				}
#endif
			}

			if ((session->request_method == GET) && (session->cgi_type == no_cgi) && (session->directory != NULL)) {
				if (session->directory->run_on_download != NULL) {
					run_program(session, session->directory->run_on_download, result);
				}
			}
			break;
		case POST:
		case unsupported:
			if (session->cgi_type != no_cgi) {
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = 405;
			}
			break;
		case PUT:
			result = handle_put_request(session);
			if (((result == 201) || (result == 204)) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case DELETE:
			result = handle_delete_request(session);
			if ((result == 204) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case WHEN:
			send_code(session);
			break;
		default:
			result = 400;
	}

	return result;
}

/* Handle timeout upon sending request
 */
static void handle_timeout(t_session *session) {
	if ((session->config->ban_on_timeout > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
		ban_ip(&(session->ip_address), session->config->ban_on_timeout, session->config->kick_on_ban);
		log_system(session, "Client banned because of connection timeout");
#ifdef ENABLE_MONITOR
		if (session->config->monitor_enabled) {
			monitor_count_ban(session);
		}
#endif
	} else {
		log_system(session, "Timeout while waiting for first request");
	}
}

/* Request has been handled, handle the return code.
 */
static void handle_request_result(t_session *session, int result) {
	char *hostname;

#ifdef ENABLE_DEBUG
	session->current_task = "handle request result";
#endif

	if (result == -1) switch (session->error_cause) {
		case ec_MAX_REQUESTSIZE:
			log_system(session, "Maximum request size reached");
			session->return_code = 413;
			send_code(session);
			if ((session->config->ban_on_max_request_size > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_max_request_size, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending a too large request");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			break;
		case ec_TIMEOUT:
			if (session->kept_alive == 0) {
				session->return_code = 408;
				send_code(session);
				handle_timeout(session);
			}
			break;
		case ec_CLIENT_DISCONNECTED:
			if (session->kept_alive == 0) {
				log_system(session, "Silent client disconnected");
			}
			break;
		case ec_SOCKET_READ_ERROR:
			if (errno != ECONNRESET) {
				log_system(session, "Error while reading request");
			}
			break;
		case ec_SOCKET_WRITE_ERROR:
			log_request(session);
			break;
		case ec_FORCE_QUIT:
			log_system(session, "Client kicked");
			break;
		case ec_SQL_INJECTION:
			if ((session->config->ban_on_sqli > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_sqli, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of SQL injection on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			session->return_code = 441;
			send_code(session);
			log_request(session);
			break;
		case ec_XSS:
			session->return_code = 442;
			send_code(session);
			log_request(session);
			break;
		case ec_CSRF:
			session->return_code = 443;
			send_code(session);
			log_request(session);
			break;
		case ec_INVALID_URL:
			if ((session->config->ban_on_invalid_url > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_invalid_url, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of invalid URL on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			send_code(session);
			break;
		default:
			if (session->data_sent == false) {
				session->return_code = 500;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
	} else switch (result) {
		case 200:
			break;
		case 201:
		case 204:
		case 304:
		case 412:
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 411:
		case 413:
			session->keep_alive = false;
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 400:
			log_garbage(session);
			if (session->data_sent == false) {
				session->return_code = 400;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
			if ((session->config->ban_on_garbage > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_garbage, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending garbage");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_bad_request(session);
			}
#endif
			break;
		case 401:
		case 403:
		case 404:
		case 501:
		case 503:
			if (session->data_sent == false) {
				switch (handle_error(session, result)) {
					case -1:
						session->keep_alive = false;
						break;
					case 200:
						break;
					default:
						if (session->data_sent == false) {
							session->return_code = result;
							if (send_code(session) == -1) {
								session->keep_alive = false;
							}
						}
				}
			}
			break;
		case 500:
			session->keep_alive = false;
		default:
			if (session->data_sent == false) {
				session->return_code = result;
				send_code(session);
			}
	}

	if ((result > 0) && (result != 400)) {
		log_request(session);
	} else {
		session->keep_alive = false;
	}
}
Пример #21
0
/* Prevent SQL injection
 */
static int prevent_sqli_str(t_session *session, char *str, int length) {
	char *data, *c, *begin, *end;
	t_sqli_pattern *pattern;
	int result = 0;

	if ((str == NULL) || (length <= 0)) {
		return 0;
	}

	if ((data = (char*)malloc(length + 1)) == NULL) {
		return -1;
	}

	memcpy(data, str, length);
	data[length] = '\0';
	url_decode(data);

	c = data;
	while (*c != '\0') {
		if (*c == '+') {
			*c = ' ';
		}
		c++;
	}

	/* Remove comments
	 */
	end = data;
	while ((begin = strstr(end, "/*")) != NULL) {
		if ((end = strstr(begin + 2, "*/")) == NULL) {
			break;
		}
		end += 2;
		memset(begin, ' ', end - begin);
	}

	/* Remove double parenthesis
	 */
	end = data;
	while ((begin = strchr(end, '(')) != NULL) {
		end = begin + 1;
		while (*end == ' ') {
			end++;
		}
		if (*end == '(') {
			*begin = ' ';
		}
	}

	/* Match patterns
	 */
	pattern = sqli_patterns;
	while (pattern != NULL) {
		if (regexec(&(pattern->regex), data, 0, NULL, 0) != REG_NOMATCH) {
			log_exploit_attempt(session, "SQLi", str);
#ifdef ENABLE_TOMAHAWK
			increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_exploit_attempt(session);
				monitor_event("SQLi attempt for %s%s", session->host->hostname.item[0], session->uri);
			}
#endif

			result = 1;
			break;
		}

		pattern = pattern->next;
	}

	free(data);

	return result;
}
Пример #22
0
static void signal2_cb(uv_signal_t* handle, int signum) {
  ASSERT(signum == SIGUSR2);
  increment_counter(&signal2_cb_counter);
  uv_signal_stop(handle);
}
Пример #23
0
/*
 * pj_ioqueue_poll()
 *
 */
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
{
    int i, count, processed;
    int msec;
    //struct epoll_event *events = ioqueue->events;
    //struct queue *queue = ioqueue->queue;
    struct epoll_event events[PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL];
    struct queue queue[PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL];
    pj_timestamp t1, t2;
    
    PJ_CHECK_STACK();

    msec = timeout ? PJ_TIME_VAL_MSEC(*timeout) : 9000;

    TRACE_((THIS_FILE, "start os_epoll_wait, msec=%d", msec));
    pj_get_timestamp(&t1);
 
    //count = os_epoll_wait( ioqueue->epfd, events, ioqueue->max, msec);
    count = os_epoll_wait( ioqueue->epfd, events, PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL, msec);
    if (count == 0) {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
    /* Check the closing keys only when there's no activity and when there are
     * pending closing keys.
     */
    if (count == 0 && !pj_list_empty(&ioqueue->closing_list)) {
	pj_lock_acquire(ioqueue->lock);
	scan_closing_keys(ioqueue);
	pj_lock_release(ioqueue->lock);
    }
#endif
	TRACE_((THIS_FILE, "os_epoll_wait timed out"));
	return count;
    }
    else if (count < 0) {
	TRACE_((THIS_FILE, "os_epoll_wait error"));
	return -pj_get_netos_error();
    }

    pj_get_timestamp(&t2);
    TRACE_((THIS_FILE, "os_epoll_wait returns %d, time=%d usec",
		       count, pj_elapsed_usec(&t1, &t2)));

    /* Lock ioqueue. */
    pj_lock_acquire(ioqueue->lock);

    for (processed=0, i=0; i<count; ++i) {
	pj_ioqueue_key_t *h = (pj_ioqueue_key_t*)(epoll_data_type)
				events[i].epoll_data;

	TRACE_((THIS_FILE, "event %d: events=%d", i, events[i].events));

	/*
	 * Check readability.
	 */
	if ((events[i].events & EPOLLIN) && 
	    (key_has_pending_read(h) || key_has_pending_accept(h)) && !IS_CLOSING(h) ) {

#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
	    queue[processed].key = h;
	    queue[processed].event_type = READABLE_EVENT;
	    ++processed;
	    continue;
	}

	/*
	 * Check for writeability.
	 */
	if ((events[i].events & EPOLLOUT) && key_has_pending_write(h) && !IS_CLOSING(h)) {

#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
	    queue[processed].key = h;
	    queue[processed].event_type = WRITEABLE_EVENT;
	    ++processed;
	    continue;
	}

#if PJ_HAS_TCP
	/*
	 * Check for completion of connect() operation.
	 */
	if ((events[i].events & EPOLLOUT) && (h->connecting) && !IS_CLOSING(h)) {

#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
	    queue[processed].key = h;
	    queue[processed].event_type = WRITEABLE_EVENT;
	    ++processed;
	    continue;
	}
#endif /* PJ_HAS_TCP */

	/*
	 * Check for error condition.
	 */
	if ((events[i].events & EPOLLERR) && !IS_CLOSING(h)) {
	    /*
	     * We need to handle this exception event.  If it's related to us
	     * connecting, report it as such.  If not, just report it as a
	     * read event and the higher layers will handle it.
	     */
	    if (h->connecting) {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
		increment_counter(h);
#endif
		queue[processed].key = h;
		queue[processed].event_type = EXCEPTION_EVENT;
		++processed;
	    } else if (key_has_pending_read(h) || key_has_pending_accept(h)) {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
		increment_counter(h);
#endif
		queue[processed].key = h;
		queue[processed].event_type = READABLE_EVENT;
		++processed;
	    }
	    continue;
	}
    }
    for (i=0; i<processed; ++i) {
	if (queue[i].key->grp_lock)
	    pj_grp_lock_add_ref_dbg(queue[i].key->grp_lock, "ioqueue", 0);
    }

    PJ_RACE_ME(5);

    pj_lock_release(ioqueue->lock);

    PJ_RACE_ME(5);

    /* Now process the events. */
    for (i=0; i<processed; ++i) {
	switch (queue[i].event_type) {
        case READABLE_EVENT:
            ioqueue_dispatch_read_event(ioqueue, queue[i].key);
            break;
        case WRITEABLE_EVENT:
            ioqueue_dispatch_write_event(ioqueue, queue[i].key);
            break;
        case EXCEPTION_EVENT:
            ioqueue_dispatch_exception_event(ioqueue, queue[i].key);
            break;
        case NO_EVENT:
            pj_assert(!"Invalid event!");
            break;
        }

#if PJ_IOQUEUE_HAS_SAFE_UNREG
	decrement_counter(queue[i].key);
#endif

	if (queue[i].key->grp_lock)
	    pj_grp_lock_dec_ref_dbg(queue[i].key->grp_lock,
	                            "ioqueue", 0);
    }

    /* Special case:
     * When epoll returns > 0 but no descriptors are actually set!
     */
    if (count > 0 && !processed && msec > 0) {
	pj_thread_sleep(msec);
    }

    pj_get_timestamp(&t1);
    TRACE_((THIS_FILE, "ioqueue_poll() returns %d, time=%d usec",
		       processed, pj_elapsed_usec(&t2, &t1)));

    return processed;
}
Пример #24
0
/* Prevent Cross-site Request Forgery
 */
int prevent_csrf(t_session *session) {
	char *referer, *slash, prev = '\0';
	int i, n;
#ifdef ENABLE_MONITOR
	char *csrf_url;
#endif

	if (session->request_method != POST) {
		return 0;
	}

	if ((referer = get_http_header("Origin:", session->http_headers)) == NULL) {
		if ((referer = get_http_header("Referer:", session->http_headers)) == NULL) {
			return 0;
		}
	}

#ifdef ENABLE_MONITOR
	csrf_url = referer;
#endif

	if (strncmp(referer, "http://", 7) == 0) {
		referer += 7;
	} else if (strncmp(referer, "https://", 8) == 0) {
		referer += 8;
	} else {
		session->request_method = GET;
		session->body = NULL;
		session->cookies = NULL;

		log_error(session, "invalid referer while checking for CSRF");

		return 1;
	}

	if ((slash = strchr(referer, '/')) != NULL) {
		n = slash - referer;
	} else {
		n = strlen(referer);
	}

	for (i = 0; i < session->host->hostname.size; i++) {
		if (strncasecmp(referer, *(session->host->hostname.item + i), n) == 0) {
			return 0;
		}
	}

	if (session->body != NULL) {
		prev = *(session->body + session->content_length);
		*(session->body + session->content_length) = '\0';
	}

	log_exploit_attempt(session, "CSRF", session->body);

	if (session->body != NULL) {
		*(session->body + session->content_length) = prev;
	}

	if (session->host->prevent_csrf == p_prevent) {
		session->request_method = GET;
		session->body = NULL;
		session->cookies = NULL;
	}

#ifdef ENABLE_TOMAHAWK
	increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
	if (session->config->monitor_enabled) {
		monitor_count_exploit_attempt(session);
		monitor_event("CSRF attempt for %s%s via %s", session->host->hostname.item[0], session->uri, csrf_url);
	}
#endif

	return 1;
}
Пример #25
0
void up_clicked(ClickRecognizerRef recognizer, void* context) {
  increment_counter();
  display_counter();
}
void up_single_click_handler(ClickRecognizerRef recognizer, Window *window) {
	increment_counter(); populate_counter_labels();
}
Пример #27
0
/*
 * pj_ioqueue_poll()
 *
 * Few things worth written:
 *
 *  - we used to do only one callback called per poll, but it didn't go
 *    very well. The reason is because on some situation, the write 
 *    callback gets called all the time, thus doesn't give the read
 *    callback to get called. This happens, for example, when user
 *    submit write operation inside the write callback.
 *    As the result, we changed the behaviour so that now multiple
 *    callbacks are called in a single poll. It should be fast too,
 *    just that we need to be carefull with the ioqueue data structs.
 *
 *  - to guarantee preemptiveness etc, the poll function must strictly
 *    work on fd_set copy of the ioqueue (not the original one).
 */
PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout)
{
    pj_fd_set_t rfdset, wfdset, xfdset;
    int count, counter;
    pj_ioqueue_key_t *h;
    struct event
    {
        pj_ioqueue_key_t	*key;
        enum ioqueue_event_type  event_type;
    } event[PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL];

    PJ_ASSERT_RETURN(ioqueue, -PJ_EINVAL);

    /* Lock ioqueue before making fd_set copies */
    pj_lock_acquire(ioqueue->lock);

    /* We will only do select() when there are sockets to be polled.
     * Otherwise select() will return error.
     */
    if (PJ_FD_COUNT(&ioqueue->rfdset)==0 &&
        PJ_FD_COUNT(&ioqueue->wfdset)==0 
#if defined(PJ_HAS_TCP) && PJ_HAS_TCP!=0
        && PJ_FD_COUNT(&ioqueue->xfdset)==0
#endif
	)
    {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
	scan_closing_keys(ioqueue);
#endif
	pj_lock_release(ioqueue->lock);
	TRACE__((THIS_FILE, "     poll: no fd is set"));
        if (timeout)
            pj_thread_sleep(PJ_TIME_VAL_MSEC(*timeout));
        return 0;
    }

    /* Copy ioqueue's pj_fd_set_t to local variables. */
    pj_memcpy(&rfdset, &ioqueue->rfdset, sizeof(pj_fd_set_t));
    pj_memcpy(&wfdset, &ioqueue->wfdset, sizeof(pj_fd_set_t));
#if PJ_HAS_TCP
    pj_memcpy(&xfdset, &ioqueue->xfdset, sizeof(pj_fd_set_t));
#else
    PJ_FD_ZERO(&xfdset);
#endif

#if VALIDATE_FD_SET
    validate_sets(ioqueue, &rfdset, &wfdset, &xfdset);
#endif

    /* Unlock ioqueue before select(). */
    pj_lock_release(ioqueue->lock);

    count = pj_sock_select(ioqueue->nfds+1, &rfdset, &wfdset, &xfdset, 
			   timeout);
    
    if (count == 0)
	return 0;
    else if (count < 0)
	return -pj_get_netos_error();
    else if (count > PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL)
        count = PJ_IOQUEUE_MAX_EVENTS_IN_SINGLE_POLL;

    /* Scan descriptor sets for event and add the events in the event
     * array to be processed later in this function. We do this so that
     * events can be processed in parallel without holding ioqueue lock.
     */
    pj_lock_acquire(ioqueue->lock);

    counter = 0;

    /* Scan for writable sockets first to handle piggy-back data
     * coming with accept().
     */
    h = ioqueue->active_list.next;
    for ( ; h!=&ioqueue->active_list && counter<count; h = h->next) {

	if ( (key_has_pending_write(h) || key_has_pending_connect(h))
	     && PJ_FD_ISSET(h->fd, &wfdset) && !IS_CLOSING(h))
        {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
            event[counter].key = h;
            event[counter].event_type = WRITEABLE_EVENT;
            ++counter;
        }

        /* Scan for readable socket. */
	if ((key_has_pending_read(h) || key_has_pending_accept(h))
            && PJ_FD_ISSET(h->fd, &rfdset) && !IS_CLOSING(h) &&
	    counter<count)
        {
#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
            event[counter].key = h;
            event[counter].event_type = READABLE_EVENT;
            ++counter;
	}

#if PJ_HAS_TCP
        if (key_has_pending_connect(h) && PJ_FD_ISSET(h->fd, &xfdset) &&
	    !IS_CLOSING(h) && counter<count) 
	{
#if PJ_IOQUEUE_HAS_SAFE_UNREG
	    increment_counter(h);
#endif
            event[counter].key = h;
            event[counter].event_type = EXCEPTION_EVENT;
            ++counter;
        }
#endif
    }

    pj_lock_release(ioqueue->lock);

    count = counter;

    /* Now process all events. The dispatch functions will take care
     * of locking in each of the key
     */
    for (counter=0; counter<count; ++counter) {
        switch (event[counter].event_type) {
        case READABLE_EVENT:
            ioqueue_dispatch_read_event(ioqueue, event[counter].key);
            break;
        case WRITEABLE_EVENT:
            ioqueue_dispatch_write_event(ioqueue, event[counter].key);
            break;
        case EXCEPTION_EVENT:
            ioqueue_dispatch_exception_event(ioqueue, event[counter].key);
            break;
        case NO_EVENT:
            pj_assert(!"Invalid event!");
            break;
        }

#if PJ_IOQUEUE_HAS_SAFE_UNREG
	decrement_counter(event[counter].key);
#endif
    }


    return count;
}
Пример #28
0
void LIRGenerator::increment_counter(address counter, BasicType type, int step) {
  LIR_Opr pointer = new_pointer_register();
  __ move(LIR_OprFact::intptrConst(counter), pointer);
  LIR_Address* addr = new LIR_Address(pointer, type);
  increment_counter(addr, step);
}