Пример #1
0
/**
 * \brief Initialize C node server and returns listen socket.
 */
int erl_init_node(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie)
{
	/* identifies a specific instance of a C node. */
	short creation = getpid();
	struct addrinfo *ai = NULL;
	struct sockaddr *addr = NULL;
	ip_addr_t ip;

	char nodename[MAXNODELEN];

	int result;
	int listen_fd;
	int port;

	unsigned timeout_ms = CONNECT_TIMEOUT;
	int epmdfd;

	/* copy the nodename into something we can modify */
	if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) {
		LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1);
		return -1;
	}

	if ((listen_fd = erl_passive_socket(hostname->s, 128, &ai)) == -1) {
		return -1;
	}

	/* use first ip address only, it's internal Erlang connection to empd */
	addr = (struct sockaddr*) ai->ai_addr;

	if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) {

		LM_CRIT("failed to initialize self as node %s\n", nodename);
		erl_close_socket(listen_fd);
		return -1;
	}

	port = sockaddr_port(addr);
	sockaddr2ip_addr(&ip, addr);

	/* publish */
	if ((epmdfd = ei_publish_tmo(ec, port, timeout_ms)) == -1) {

		LM_ERR("Failed to publish port %u to epmd, check is epmd started\n", port);

		erl_close_socket(listen_fd);
		return -1;
	} else {
		LM_DBG("listen on %s:%u[%u]/[%d] as %s\n",ip_addr2strz(&ip),port,listen_fd,epmdfd,nodename);
	}

	freeaddrinfo(ai);
	return listen_fd;
}
Пример #2
0
/**
 * @brief Initialize Erlang connection
 */
int erl_init_ec(ei_cnode *ec, const str *alivename, const str *hostname, const str *cookie)
{
	/* identifies a specific instance of a C node. */
	short creation = getpid();
	struct addrinfo *ai = NULL;
	struct sockaddr *addr = NULL;
	ip_addr_t ip;

	char nodename[MAXNODELEN];

	int result;
	int port;

	/* copy the nodename into something we can modify */
	if (snprintf(nodename, MAXNODELEN, "%.*s@%.*s", STR_FMT(alivename), STR_FMT(hostname)) >= MAXNODELEN) {
		LM_CRIT("the node name %.*s@%.*s is too large max length allowed is %d\n", STR_FMT(alivename), STR_FMT(hostname), MAXNODELEN-1);
		return -1;
	}

	if (erl_active_socket(hostname->s, 128, &ai)) {
		return -1;
	}

	addr = (struct sockaddr*) ai->ai_addr;
	sockaddr2ip_addr(&ip,addr);

	if ((result = ei_connect_xinit(ec, hostname->s, alivename->s, nodename, (Erl_IpAddr) &(((struct sockaddr_in*)ai->ai_addr)->sin_addr), cookie->s, creation)) < 0) {

		LM_CRIT("failed to initialize self as cnode name %s\n", nodename);
		return -1;
	}

	port = sockaddr_port(addr);

	LM_DBG("initialized ec for cnode '%s' on %.*s[%s] creation %d.\n", nodename, STR_FMT(hostname), ip_addr2strz(&ip), creation);

	freeaddrinfo(ai);
	return 0;
}
Пример #3
0
/* Generate the NAT-D payload hash : HASH(CKY-I | CKY-R | IP | Port).  */
static u_int8_t *
nat_t_generate_nat_d_hash(struct message *msg, struct sockaddr *sa,
    size_t *hashlen)
{
	struct ipsec_exch *ie = (struct ipsec_exch *)msg->exchange->data;
	struct hash	 *hash;
	u_int8_t	 *res;
	in_port_t	  port;

	hash = hash_get(ie->hash->type);
	if (hash == NULL) {
		log_print ("nat_t_generate_nat_d_hash: no hash");
		return NULL;
	}

	*hashlen = hash->hashsize;

	res = malloc(*hashlen);
	if (!res) {
		log_print("nat_t_generate_nat_d_hash: malloc (%lu) failed",
		    (unsigned long)*hashlen);
		*hashlen = 0;
		return NULL;
	}

	port = sockaddr_port(sa);
	bzero(res, *hashlen);

	hash->Init(hash->ctx);
	hash->Update(hash->ctx, msg->exchange->cookies,
	    sizeof msg->exchange->cookies);
	hash->Update(hash->ctx, sockaddr_addrdata(sa), sockaddr_addrlen(sa));
	hash->Update(hash->ctx, (unsigned char *)&port, sizeof port);
	hash->Final(res, hash->ctx);
	return res;
}
Пример #4
0
static term_t ol_tcp_acc_control(outlet_t *ol,
		uint32_t op, uint8_t *data, int dlen, term_t reply_to, heap_t *hp)
{
	char rbuf[256];
	char *reply = rbuf;

	assert(ol != 0);
	assert(ol->tcp != 0);
	debug("%s(op=%d)\n", __FUNCTION__, op);

	switch (op)
	{
	case INET_REQ_ACCEPT:
	{
		if (dlen != 4)
			goto error;

		uint32_t millis = GET_UINT_32(data);
		if (millis == 0)
		{
			// immediate reply requested
			if (ol->accepting != 0 && ol->accepted != 0)
			{
				struct	proc_t *cont_proc = scheduler_lookup(reply_to);
				assert(cont_proc != 0);

				bake_one_accepted(ol, cont_proc);
			}
			else
				inet_async_error(ol->oid, reply_to, ASYNC_REF, A_TIMEOUT);

			break;
		}

		acc_pend_t *pend = get_free_pending(ol);
		if (pend == 0)
		{
			REPLY_INET_ERROR("emfile");
			break;
		}
		pend->outlet = ol;
		pend->reply_to = reply_to;
		pend->timeout_set = 0;
		if (millis != INET_INFINITY)
		{
			tcp_accept_timeout(pend, millis);
			pend->timeout_set = 1;
		}

		append_to_ring(&ol->accepting, pend);
		bake_all_accepted(ol);

		*reply++ = INET_REP_OK;
		uint16_t ref = ASYNC_REF;
		PUT_UINT_16(reply, ref);
		reply += 2;
	}
	break;

	case INET_REQ_NAME:
	{
		saddr_t sockaddr;
		if (ol_tcp_getsockname(ol, &sockaddr))
			goto error;

		int family;
		switch (sockaddr.saddr.sa_family) {
		case AF_INET:  family = INET_AF_INET;  break;
		case AF_INET6: family = INET_AF_INET6; break;
		default: goto error;
		}
		*reply++ = INET_REP_OK;
		*reply++ = family;

		PUT_UINT_16(reply, sockaddr_port(&sockaddr.saddr));
		reply += 2;

		size_t alen = saddr_to_ipaddr(&sockaddr, (ipX_addr_t *)reply);
		reply += alen;
	}
	break;

	case INET_REQ_SETOPTS:
	if (ol_tcp_acc_set_opts(ol, data, dlen) < 0)
		goto error;

	*reply++ = INET_REP_OK;
	break;

	case INET_REQ_GETOPTS:
	{
		int sz = ol_tcp_acc_get_opts(ol, data, dlen, rbuf+1, sizeof(rbuf) -1);
		if (sz < 0)
			goto error;

		*reply++ = INET_REP_OK;
		reply += sz;
	}
	break;

	default:
error:
		REPLY_INET_ERROR("einval");
	}

	int rlen = reply -rbuf;
	assert(rlen >= 1 && rlen <= sizeof(rbuf));
	term_t result = heap_str_N(hp, rbuf, rlen);
	if (result == noval)
		return A_NO_MEMORY;

	return result;
}
Пример #5
0
/** \brief allocate & bind a server socket using TCP.
 *
 * 	Allocate & bind a server socket using TCP.
 *
 */
int erl_passive_socket(const char *hostname, int qlen,
		struct addrinfo **ai_ret)
{
	int sockfd; /* socket descriptor and socket type	*/
	int on = 1;
	int error_num = 0;
	int port;
	struct addrinfo *ai;
	struct addrinfo hints;
	struct ip_addr ip;
	socklen_t addrlen = sizeof(struct sockaddr);

	memset(&hints, 0, sizeof(struct addrinfo));

	hints.ai_family = AF_UNSPEC;
	/* = AF_INET;  IPv4 address family */
	/* = AF_UNSPEC; Allow IPv4 or IPv6 */
	hints.ai_socktype = SOCK_STREAM;
	hints.ai_flags = AI_V4MAPPED;
	hints.ai_protocol = IPPROTO_TCP;

	if ((error_num = getaddrinfo(hostname, 0 /* unused */, &hints, &ai)))
	{
		LM_CRIT("failed to resolve %s: %s\n", hostname, gai_strerror(error_num));
		return -1;
	}

	/* Allocate a socket */
	sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
	if (sockfd < 0)
	{
		LM_CRIT("failed to create socket. %s.\n", strerror(errno));
		freeaddrinfo(ai);
		return -1;
	}

	/* initialize TCP */
#if  !defined(TCP_DONT_REUSEADDR)
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int))) {
		LM_ERR("failed to enable SO_REUSEADDR for socket on %s %s, %s\n",
				hostname, ip_addr2strz(&ip), strerror(errno));
	}
#endif
	/* tos */
	on=IPTOS_LOWDELAY;
	if (setsockopt(sockfd, IPPROTO_IP, IP_TOS, (void*)&on,sizeof(on)) ==-1) {
			LM_WARN("setsockopt tos: %s\n", strerror(errno));
			/* continue since this is not critical */
	}

	/* Bind the socket */
	if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0)
	{
		port=sockaddr_port(ai->ai_addr);
		LM_CRIT("failed to bind socket on %s %s:%u. %s.\n", hostname,
				ip_addr2strz(&ip), port, strerror(errno));

		erl_close_socket(sockfd);
		freeaddrinfo(ai);
		return -1;
	}

	if (ai->ai_socktype == SOCK_STREAM && listen(sockfd, qlen) < 0)
	{
		LM_CRIT("failed to listen socket on %s, %s. %s.\n", hostname,
				ip_addr2strz(&ip), strerror(errno));

		erl_close_socket(sockfd);
		freeaddrinfo(ai);

		return -1;
	}

	/* get addr on socket */
	if (getsockname(sockfd, ai->ai_addr, &addrlen)){
		LM_ERR("getsockname failed: %s\n",strerror(errno));
	}

	if (ai_ret && *ai_ret == NULL)
	{
		*ai_ret = ai;
	}
	else if (ai_ret)
	{
		freeaddrinfo(*ai_ret);
		*ai_ret = ai;
	}
	else
	{
		freeaddrinfo(ai);
	}

	return sockfd;
}
Пример #6
0
static int rosedb_log_message(char *stream, size_t *maxlen, knot_pkt_t *pkt,
                              const char *threat_code, struct query_data *qdata)
{
	char dname_buf[KNOT_DNAME_MAXLEN] = {'\0'};
	struct sockaddr_storage addr;
	socklen_t addr_len = sizeof(addr);
	time_t now = time(NULL);
	struct tm tm;
	gmtime_r(&now, &tm);

	/* Field 1 Timestamp (UTC). */
	STREAM_WRITE(stream, maxlen, strftime, "%Y-%m-%d %H:%M:%S\t", &tm);

	/* Field 2/3 Remote, local address. */
	const struct sockaddr *remote = (const struct sockaddr *)qdata->param->remote;
	memcpy(&addr, remote, sockaddr_len(remote));
	int client_port = sockaddr_port(&addr);
	sockaddr_port_set(&addr, 0);
	STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr);
	STREAM_WRITE(stream, maxlen, snprintf, "\t");
	getsockname(qdata->param->socket, (struct sockaddr *)&addr, &addr_len);
	int server_port = sockaddr_port(&addr);
	sockaddr_port_set(&addr, 0);
	STREAM_WRITE(stream, maxlen, sockaddr_tostr, &addr);
	STREAM_WRITE(stream, maxlen, snprintf, "\t");

	/* Field 4/5 Local, remote port. */
	STREAM_WRITE(stream, maxlen, snprintf, "%d\t%d\t", client_port, server_port);

	/* Field 6 Threat ID. */
	STREAM_WRITE(stream, maxlen, snprintf, "%s\t", threat_code);

	/* Field 7 - 13 NULL */
	STREAM_WRITE(stream, maxlen, snprintf, "\t\t\t\t\t\t\t");

	/* Field 14 QNAME */
	knot_dname_to_str(dname_buf, knot_pkt_qname(qdata->query), sizeof(dname_buf));
	STREAM_WRITE(stream, maxlen, snprintf, "%s\t", dname_buf);

	/* Field 15 Resolution (0 = local, 1 = lookup)*/
	STREAM_WRITE(stream, maxlen, snprintf, "0\t");

	/* Field 16 RDATA.
	 * - Return randomly RDATA in the answer section (probabilistic rotation).
	 * - Empty if no answer.
	 */
	const knot_pktsection_t *ans = knot_pkt_section(pkt, KNOT_ANSWER);
	if (ans->count > 0) {
		const knot_rrset_t *rr = &ans->rr[knot_random_uint16_t() % ans->count];
		int ret = knot_rrset_txt_dump_data(rr, 0, stream, *maxlen, &KNOT_DUMP_STYLE_DEFAULT);
		if (ret < 0) {
			return ret;
		}
		stream_skip(&stream, maxlen, ret);
	}
	STREAM_WRITE(stream, maxlen, snprintf, "\t");

	/* Field 17 Connection type. */
	STREAM_WRITE(stream, maxlen, snprintf, "%s\t",
	             net_is_connected(qdata->param->socket) ? "TCP" : "UDP");

	/* Field 18 Query type. */
	char type_str[16] = { '\0' };
	knot_rrtype_to_string(knot_pkt_qtype(qdata->query), type_str, sizeof(type_str));
	STREAM_WRITE(stream, maxlen, snprintf, "%s\t", type_str);

	/* Field 19 First authority. */
	const knot_pktsection_t *ns = knot_pkt_section(pkt, KNOT_AUTHORITY);
	if (ns->count > 0 && ns->rr[0].type == KNOT_RRTYPE_NS) {
		const knot_dname_t *label = knot_ns_name(&ns->rr[0].rrs, 0);
		memset(dname_buf, 0, sizeof(dname_buf));
		memcpy(dname_buf, label + 1, *label);
		STREAM_WRITE(stream, maxlen, snprintf, "%s", dname_buf);
	}

	return KNOT_EOK;
}