Exemplo n.º 1
0
void
tfw_destroy_server(struct sock *s)
{
	TfwConnection *conn = s->sk_user_data;
	TfwServer *srv;

	BUG_ON(!conn);
	srv = conn->hndl;

	/* The call back can be called twise bou our and Linux code. */
	if (unlikely(!srv))
		return;

	TFW_DBG("Destroy server socket %p\n", s);

	if (tfw_sched_del_srv(srv))
		TFW_WARN("Try to delete orphaned server from"
			 " requests scheduler");

	srv->sock = NULL;
	conn->hndl = NULL;

	/* FIXME clear the server references from all current sessions. */
#if 0
	kmem_cache_free(srv_cache, srv);
#endif

	conn->sk_destruct(s);
}
Exemplo n.º 2
0
/**
 * Grow @str for @n new chunks.
 * New branches of the string tree are created on 2nd level only,
 * i.e. there is no possibility to grow number of chunks of duplicate string.
 * Pass pointer to one of the duplicates to do so.
 * @return pointer to the first of newly added chunk.
 *
 * TODO do we need exponential growing?
 */
static TfwStr *
__str_grow_tree(TfwPool *pool, TfwStr *str, unsigned int flag, int n)
{
	if (str->flags & flag) {
		unsigned int l;
		void *p;

		if (unlikely(TFW_STR_CHUNKN_LIM(str))) {
			TFW_WARN("Reaching chunks hard limit\n");
			return NULL;
		}

		l = TFW_STR_CHUNKN(str) * sizeof(TfwStr);
		p = tfw_pool_realloc(pool, str->ptr, l,
				     l + n * sizeof(TfwStr));
		if (!p)
			return NULL;
		str->ptr = p;
		TFW_STR_CHUNKN_ADD(str, n);
	}
	else {
		TfwStr *a = tfw_pool_alloc(pool, (n + 1) * sizeof(TfwStr));
		if (!a)
			return NULL;
		a[0] = *str;
		str->ptr = a;
		__TFW_STR_CHUNKN_SET(str, n + 1);
	}

	str = (TfwStr *)str->ptr + TFW_STR_CHUNKN(str) - n;
	memset(str, 0, sizeof(TfwStr) * n);

	return str;
}
Exemplo n.º 3
0
/**
 * Create a file in the debugfs, also create parent directories if needed and
 * remove the old file if it exists.
 *
 * @param path  Path to a file to be created.
 *              The path is always treated relative to the Tempesta root
 *              directory in the debugfs (see tfw_debugfs_root).
 * @param data  A pointer to some data which is saved in 'file' and 'inode'
 *              structures. It may be retrieved by any function in @fops as
 *              file->private_data or file->f_inode->i_private (it is copied
 *              into both places).
 * @param fops  A set of functions that handle system calls on the created file.
 *
 *
 * The function creates a file in the debugfs, but does it in a robust way:
 *  - the file is replaced if it already exists
 *  - all parent directories are created if they don't exist
 *
 * Returns: An ERR_PTR if the file is not created.
 */
static struct dentry *
create_with_parents(const char *path, void *data,
		    const struct file_operations *fops)
{
	size_t name_size;
	char *buf, *pos, *component;
	struct dentry *parent, *child;

	/* Copy the path to a temporary buffer where it can be modified. */
	name_size = strlen(path) + 1;
	buf = kmalloc(name_size, GFP_KERNEL);
	BUG_ON(ZERO_OR_NULL_PTR(buf));
	strlcpy(buf, path, name_size);

	/* Eat the leading slash to allow specify either /foo/bar or foo/bar */
	pos = buf;
	if (*pos == '/')
		++pos;

	/* Walk over the path and create non-existing directories. */
	parent = tfw_debugfs_root;
	component = pos;
	do {
		if (*pos != '/')
			continue;

		*pos = '\0';
		child = lookup_file(component, parent);
		if (!child) {
			child = debugfs_create_dir(component, parent);
			BUG_ON(!parent);
		}
		parent = child;
		component = pos + 1;
	} while (*(++pos));

	/* Remove the file if it already exists. */
	child = lookup_file(component, parent);
	if (child) {
		TFW_DBG("Removing already existing debugfs file: %s\n", path);
		debugfs_remove(child);
	}

	/* Create the actual file. */
	child = debugfs_create_file(component, S_IRWXU, parent, data, fops);
	if (IS_ERR_OR_NULL(child)) {
		int err = PTR_ERR(child);
		TFW_WARN("Can't create debugfs file: %s (%d)\n", path, err);
	} else {
		TFW_DBG("Created debugfs file: %s\n", path);
	}

	kfree(buf);

	return child;
}
Exemplo n.º 4
0
/**
 * Initialize the debugfs wrapper by creating a directory in the debugfs
 * where all files owned by the Tempesta FW are hosted.
 */
int
tfw_debugfs_init(void)
{
	int ret = 0;

	tfw_debugfs_root = debugfs_create_dir(TFW_DEBUGFS_ROOT_NAME, NULL);

	if (IS_ERR_OR_NULL(tfw_debugfs_root)) {
		ret = (int)PTR_ERR(tfw_debugfs_root);
		TFW_WARN("Can't create debugfs directory (%d)\n", ret);
	}

	return ret;
}
Exemplo n.º 5
0
static void
tfw_bmb_msg_send(int tn, int cn)
{
	TfwBmbTask *task = &bmb_task[tn];
	int fz_tries = 0, r;
	TfwStr msg;
	TfwHttpMsg req;
	TfwMsgIter it;

	BUG_ON(!task->conn[cn].sk);

	do {
		if (++fz_tries > 10) {
			TFW_ERR("Too many fuzzer tries to generate request\n");
			return;
		}

		r = fuzz_gen(&task->ctx, task->buf, task->buf + BUF_SIZE, 0, 1,
			     FUZZ_REQ);
		if (r < 0) {
			TFW_ERR("Cannot generate HTTP request, r=%d\n", r);
			return;
		}
		if (r == FUZZ_END)
			fuzz_init(&task->ctx, true);
	} while (r != FUZZ_VALID);

	msg.ptr = task->buf;
	msg.skb = NULL;
	msg.len = strlen(msg.ptr);
	msg.flags = 0;

	if (!tfw_http_msg_create(&req, &it, Conn_Clnt, msg.len)) {
		TFW_WARN("Cannot create HTTP request.\n");
		return;
	}

	if (verbose)
		TFW_LOG("Send request:\n"
			"------------------------------\n"
			"%s\n"
			"------------------------------\n",
			task->buf);

	tfw_http_msg_write(&it, &req, &msg);
	ss_send(task->conn[cn].sk, &req.msg.skb_list, true);

	atomic_inc(&bmb_request_send);
}
Exemplo n.º 6
0
/*
 * Find a connection for an outgoing HTTP request.
 *
 * The search is based on contents of an HTTP request and match rules
 * that specify which Server Group the request should be forwarded to.
 */
static TfwConnection *
tfw_sched_http_sched_grp(TfwMsg *msg)
{
	TfwSrvGroup *sg;
	TfwConnection *conn;
	TfwSchedHttpRule *rule;

	if(!tfw_sched_http_rules || list_empty(&tfw_sched_http_rules->list))
		return NULL;

	rule = tfw_http_match_req_entry((TfwHttpReq *)msg, tfw_sched_http_rules,
					TfwSchedHttpRule, rule);
	if (unlikely(!rule)) {
		TFW_DBG("sched_http: No matching rule found.\n");
		return NULL;
	}

	sg = rule->main_sg;
	BUG_ON(!sg);
	TFW_DBG("sched_http: use server group: '%s'\n", sg->name);

	conn = sg->sched->sched_srv(msg, sg);

	if (unlikely(!conn && rule->backup_sg)) {
		sg = rule->backup_sg;
		TFW_DBG("sched_http: the main group is offline, use backup:"
			" '%s'\n", sg->name);
		conn = sg->sched->sched_srv(msg, sg);
	}

	if (unlikely(!conn))
		TFW_WARN("sched_http: Unable to select server from group"
			 " '%s'\n", sg->name);

	return conn;
}
Exemplo n.º 7
0
/**
 * Work to copy response skbs to database mapped area.
 *
 * It's nasty to copy data on CPU, but we can't use DMA for mmaped file
 * as well as for unaligned memory areas.
 */
static void
tfw_cache_copy_resp(struct work_struct *work)
{
	int i;
	size_t hlens, tot_len;
	long n;
	char *p;
	TfwCWork *cw = (TfwCWork *)work;
	TfwCacheEntry *ce = cw->cw_ce;
	TdbVRec *trec;
	TfwHttpHdrTbl *htbl;
	TfwHttpHdr *hdr;

	BUG_ON(!ce->resp);

	/* Write HTTP headers. */
	htbl = ce->resp->h_tbl;
	ce->hdr_num = htbl->size;

	hlens = sizeof(ce->hdr_lens[0]) * ce->hdr_num;
	tot_len = hlens + ce->resp->msg.len;

	/*
	 * Try to place the cached response in single memory chunk.
	 *
	 * Number of HTTP headers is limited by TFW_HTTP_HDR_NUM_MAX while TDB
	 * should be able to allocate an empty page if we issued a large
	 * request. So HTTP header lengths must fit the first allocated data
	 * chunk, also there must be some space for headers and message bodies.
	 */
	trec = tdb_entry_add(db, (TdbVRec *)ce, tot_len);
	if (!trec || trec->len <= hlens) {
		TFW_WARN("Cannot allocate memory to cache HTTP headers."
			 " Probably TDB cache is exhausted.\n");
		goto err;
	}
	p = (char *)(trec + 1) + hlens;
	tot_len -= hlens;

	/*
	 * Set start of headers pointer just after array of
	 * header length.
	 */
	ce->hdrs = p;
	hdr = htbl->tbl;
	for (i = 0; i < hlens / sizeof(ce->hdr_lens[0]); ++i, ++hdr) {
		n = tfw_cache_copy_str_compound(&p, &trec, &hdr->field,
						tot_len);
		if (n < 0) {
			TFW_ERR("Cache: cannot copy HTTP header\n");
			goto err;
		}
		BUG_ON(n > tot_len);
		tot_len -= n;
	}

	/* Write HTTP response body. */
	ce->body = p;
	n = tfw_cache_copy_str_compound(&p, &trec, &ce->resp->body, tot_len);
	if (n < 0) {
		TFW_ERR("Cache: cannot copy HTTP body\n");
		goto err;
	}
	ce->body_len = n;

err:
	/* FIXME all allocated TDB blocks are leaked here. */
	kmem_cache_free(c_cache, cw);
}