Beispiel #1
0
/* See lookup_ip's comment */
struct dns_query *
lookup_hostname(const char *ip, DNSCB callback, void *data)
{
	struct dns_query *query = rb_malloc(sizeof(struct dns_query));
	int aftype;

	if(!rb_inet_pton_sock(ip, (struct sockaddr *)&query->addr))
	{
		rb_free(query);
		return NULL;
	}

	aftype = GET_SS_FAMILY(&query->addr);

	if(aftype == AF_INET)
		query->type = QUERY_PTR_A;
	else if(aftype == AF_INET6)
		query->type = QUERY_PTR_AAAA;
	else
	{
		rb_free(query);
		return NULL;
	}

	query->id = query_count++;
	query->callback = callback;
	query->data = data;

	query->query.ptr = query;
	query->query.callback = handle_lookup_hostname_reply;

	gethost_byaddr(&query->addr, &query->query);

	return query;
}
Beispiel #2
0
/* Callback from gethost_byname_type */
static void
handle_lookup_ip_reply(void *data, struct DNSReply *reply)
{
	struct dns_query *query = data;
	char ip[HOSTIPLEN] = "*";

	if(query == NULL)
	{
		/* Shouldn't happen */
		warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: query == NULL!");
		exit(EX_DNS_ERROR);
	}

	if(reply == NULL)
		goto end;

	switch(query->type)
	{
	case QUERY_A:
		if(GET_SS_FAMILY(&reply->addr) == AF_INET)
			rb_inet_ntop_sock((struct sockaddr *)&reply->addr, ip, sizeof(ip));
		break;
	case QUERY_AAAA:
		if(GET_SS_FAMILY(&reply->addr) == AF_INET6)
		{
			rb_inet_ntop_sock((struct sockaddr *)&reply->addr, ip, sizeof(ip));
			if(ip[0] == ':')
			{
				memmove(&ip[1], ip, strlen(ip));
				ip[0] = '0';
			}
		}
		break;
	default:
		warn_opers(L_CRIT, "DNS: handle_lookup_ip_reply: unknown query type %d",
				query->type);
		exit(EX_DNS_ERROR);
	}

end:
	if(query->callback)
		query->callback(ip, ip[0] != '*', query->type, query->data);

	rb_free(query);
}
Beispiel #3
0
static void
resolve_ip(char **parv)
{
	char *requestid = parv[1];
	char *iptype = parv[2];
	char *rec = parv[3];
	int aftype;
	struct dns_request *req;
	if(strlen(requestid) >= REQIDLEN)
		exit(3);

	req = rb_malloc(sizeof(struct dns_request));
	req->revfwd = REQREV;
	strcpy(req->reqid, requestid);

	if(!rb_inet_pton_sock(rec, (struct sockaddr *)&req->addr))
		exit(6);

	aftype = GET_SS_FAMILY(&req->addr);
	switch (*iptype)
	{
	case '4':
		req->reqtype = REVIPV4;
		if(aftype != AF_INET)
			exit(6);
		break;
	case '6':
		req->reqtype = REVIPV6;
		if(aftype != AF_INET6)
			exit(6);
		break;
	default:
		exit(7);
	}
	req->query.ptr = req;
	req->query.callback = send_answer;
	gethost_byaddr(&req->addr, &req->query);
}
Beispiel #4
0
static int
inetport(struct Listener *listener)
{
	rb_fde_t *F;
	int ret;
	int opt = 1;

	/*
	 * At first, open a new socket
	 */
	
	F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket");

#ifdef RB_IPV6
	if(listener->addr.ss_family == AF_INET6)
	{
		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr;
		if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any))
		{
			rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	} else
#endif
	{
		struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr;
		if(in->sin_addr.s_addr != INADDR_ANY)
		{
			rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}	
	}

	if(F == NULL)
	{
		ilog_error("opening listener socket");
		return 0;
	}
	else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/
	{
		ilog_error("no more connections left for listener");
		rb_close(F);
		return 0;
	}

	/*
	 * XXX - we don't want to do all this crap for a listener
	 * set_sock_opts(listener);
	 */
	if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
	{
		ilog_error("setting SO_REUSEADDR for listener");
		rb_close(F);
		return 0;
	}

	/*
	 * Bind a port to listen for new connections if port is non-null,
	 * else assume it is already open and try get something from it.
	 */

	if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr)))
	{
		ilog_error("binding listener socket");
		rb_close(F);
		return 0;
	}

	if((ret = rb_listen(F, RATBOX_SOMAXCONN)))
	{
		ilog_error("listen()");
		rb_close(F);
		return 0;
	}

	listener->F = F;

	rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener);
	return 1;
}
Beispiel #5
0
static int
inetport(struct Listener *listener)
{
	rb_fde_t *F;
	int opt = 1;
	const char *errstr;

	/*
	 * At first, open a new socket
	 */

	F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket");

#ifdef RB_IPV6
	if(listener->addr.ss_family == AF_INET6)
	{
		struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr;
		if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any))
		{
			rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	} else
#endif
	{
		struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr;
		if(in->sin_addr.s_addr != INADDR_ANY)
		{
			rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	}

	if(F == NULL)
	{
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"Cannot open socket for listener on port %d",
				get_listener_port(listener));
		ilog(L_MAIN, "Cannot open socket for listener %s",
				get_listener_name(listener));
		return 0;
	}
	else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/
	{
		ilog_error("no more connections left for listener");
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"No more connections left for listener on port %d",
				get_listener_port(listener));
		ilog(L_MAIN, "No more connections left for listener %s",
				get_listener_name(listener));
		rb_close(F);
		return 0;
	}

	/*
	 * XXX - we don't want to do all this crap for a listener
	 * set_sock_opts(listener);
	 */
	if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
	{
		errstr = strerror(rb_get_sockerr(F));
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"Cannot set SO_REUSEADDR for listener on port %d: %s",
				get_listener_port(listener), errstr);
		ilog(L_MAIN, "Cannot set SO_REUSEADDR for listener %s: %s",
				get_listener_name(listener), errstr);
		rb_close(F);
		return 0;
	}

	/*
	 * Bind a port to listen for new connections if port is non-null,
	 * else assume it is already open and try get something from it.
	 */

	if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr)))
	{
		errstr = strerror(rb_get_sockerr(F));
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"Cannot bind for listener on port %d: %s",
				get_listener_port(listener), errstr);
		ilog(L_MAIN, "Cannot bind for listener %s: %s",
				get_listener_name(listener), errstr);
		rb_close(F);
		return 0;
	}

	if(rb_listen(F, CHARYBDIS_SOMAXCONN, listener->defer_accept))
	{
		errstr = strerror(rb_get_sockerr(F));
		sendto_realops_snomask(SNO_GENERAL, L_ALL,
				"Cannot listen() for listener on port %d: %s",
				get_listener_port(listener), errstr);
		ilog(L_MAIN, "Cannot listen() for listener %s: %s",
				get_listener_name(listener), errstr);
		rb_close(F);
		return 0;
	}

	listener->F = F;

	rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener);
	return 1;
}
Beispiel #6
0
/*
 * mr_webirc - webirc message handler
 *      parv[1] = password
 *      parv[2] = fake username (we ignore this)
 *	parv[3] = fake hostname
 *	parv[4] = fake ip
 */
static void
mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{
	struct ConfItem *aconf;
	const char *encr;
	struct rb_sockaddr_storage addr;

	aconf = find_address_conf(client_p->host, client_p->sockhost,
				IsGotId(client_p) ? client_p->username : "******",
				IsGotId(client_p) ? client_p->username : "******",
				(struct sockaddr *) &client_p->localClient->ip,
				GET_SS_FAMILY(&client_p->localClient->ip), NULL);
	if (aconf == NULL || !(aconf->status & CONF_CLIENT))
		return;
	if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc."))
	{
		/* XXX */
		sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block");
		return;
	}
	if (EmptyString(aconf->passwd))
	{
		sendto_one(source_p, "NOTICE * :CGI:IRC auth blocks must have a password");
		return;
	}

	if (EmptyString(parv[1]))
		encr = "";
	else if (IsConfEncrypted(aconf))
		encr = rb_crypt(parv[1], aconf->passwd);
	else
		encr = parv[1];

	if (encr == NULL || strcmp(encr, aconf->passwd))
	{
		sendto_one(source_p, "NOTICE * :CGI:IRC password incorrect");
		return;
	}

	if (rb_inet_pton_sock(parv[4], (struct sockaddr *)&addr) <= 0)
	{
		sendto_one(source_p, "NOTICE * :Invalid IP");
		return;
	}

	source_p->localClient->ip = addr;

	rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, source_p->sockhost, sizeof(source_p->sockhost));

	if(strlen(parv[3]) <= HOSTLEN)
		rb_strlcpy(source_p->host, parv[3], sizeof(source_p->host));
	else
		rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));

	/* Check dlines now, klines will be checked on registration */
	if((aconf = find_dline((struct sockaddr *)&source_p->localClient->ip,
			       GET_SS_FAMILY(&source_p->localClient->ip))))
	{
		if(!(aconf->status & CONF_EXEMPTDLINE))
		{
			exit_client(client_p, source_p, &me, "D-lined");
			return;
		}
	}

	sendto_one(source_p, "NOTICE * :CGI:IRC host/IP set to %s %s", parv[3], parv[4]);
}
Beispiel #7
0
static void
send_answer(void *vptr, struct DNSReply *reply)
{
	struct dns_request *req = (struct dns_request *)vptr;
	char response[64];
	int result = 0;
	int aftype = 0;
	strcpy(response, "FAILED");

	if(reply != NULL)
	{
		switch (req->revfwd)
		{
		case REQREV:
			{
				if(req->reqtype == REVIPV4)
				{
					struct sockaddr_in *ip, *ip_fwd;
					ip = (struct sockaddr_in *)&req->addr;
					ip_fwd = (struct sockaddr_in *)&reply->addr;
					aftype = 4;
					if(ip->sin_addr.s_addr != ip_fwd->sin_addr.s_addr)
					{
						result = 0;
						break;
					}
				}
#ifdef RB_IPV6
				else if(req->reqtype == REVIPV6)
				{
					struct sockaddr_in6 *ip, *ip_fwd;
					ip = (struct sockaddr_in6 *)&req->addr;
					ip_fwd = (struct sockaddr_in6 *)&reply->addr;
					aftype = 6;
					if(memcmp
					   (&ip->sin6_addr, &ip_fwd->sin6_addr,
					    sizeof(struct in6_addr)) != 0)
					{
						result = 0;
						break;
					}
				}
#endif
				else
				{
					/* uhh wut? */
					result = 0;
					break;
				}

				if(strlen(reply->h_name) < 63)
				{
					strcpy(response, reply->h_name);
					result = 1;
				}
				else
				{
					strcpy(response, "HOSTTOOLONG");
					result = 0;
				}
				break;
			}

		case REQFWD:
			{
#ifdef RB_IPV6
				if(GET_SS_FAMILY(&reply->addr) == AF_INET6)
				{
					char tmpres[65];
					rb_inet_ntop_sock((struct sockaddr *)&reply->addr,
						     tmpres, sizeof(tmpres) - 1);
					aftype = 6;
					if(*tmpres == ':')
					{
						strcpy(response, "0");
						strcat(response, tmpres);
					}
					else
						strcpy(response, tmpres);
					result = 1;
					break;
				}
				else
#endif
				if(GET_SS_FAMILY(&reply->addr) == AF_INET)
				{
					result = 1;
					aftype = 4;
					rb_inet_ntop_sock((struct sockaddr *)&reply->addr,
						     response, sizeof(response));
					break;
				}
				else
					break;
			}
		default:
			{
				exit(1);
			}
		}

	}
	rb_helper_write(res_helper, "R %s %d %d %s\n", req->reqid, result, aftype, response);
	rb_free(req);
}