#include "hash.h"
#include "ircd_log.h"
#include "ircd_osdep.h"
+#include "ircd_reply.h"
#include "ircd_string.h"
#include "ircd.h"
#include "list.h"
#include "listener.h"
+#include "msg.h"
#include "numeric.h"
#include "numnicks.h"
#include "packet.h"
#include "struct.h"
#include "support.h"
#include "sys.h"
+#include "uping.h"
#include "version.h"
#include <arpa/inet.h>
#include <sys/poll.h>
#endif /* USE_POLL */
-#ifndef IN_LOOPBACKNET
-#define IN_LOOPBACKNET 0x7f
-#endif
-
#ifndef INADDR_NONE
#define INADDR_NONE 0xffffffff
#endif
struct Client* LocalClientArray[MAXCONNECTIONS];
int HighestFd = -1;
-static struct sockaddr_in virtualHost;
+struct sockaddr_in VirtualHost;
static char readbuf[SERVER_TCP_WINDOW];
-static int running_in_background;
/*
* report_error text constants
const char* const SETBUFS_ERROR_MSG = "error setting buffer size for %s: %s";
const char* const SOCKET_ERROR_MSG = "error creating socket for %s: %s";
-#ifdef VIRTUAL_HOST
-struct sockaddr_in vserv;
-#endif
#ifdef GODMODE
#ifndef NODNS
static time_t last_notice = 0;
int errtmp = errno; /* debug may change 'errno' */
const char* errmsg = (err) ? strerror(err) : "";
-
- if (!who)
+ if (!errmsg)
+ errmsg = "Unknown error";
+
+ if (EmptyString(who))
who = "unknown";
if (last_notice + 20 < CurrentTime) {
/*
* pace error messages so opers don't get flooded by transients
*/
- sendto_ops(text, who, errmsg);
+ sendto_opmask_butone(0, SNO_OLDSNO, text, who, errmsg);
last_notice = CurrentTime;
}
-
ircd_log(L_ERROR, text, who, errmsg);
-
- if (!running_in_background) {
- fprintf(stderr, text, who, errmsg);
- fprintf(stderr, "\n");
- }
errno = errtmp;
}
connect_server(aconf, 0, reply);
}
else
- sendto_ops("Connect to %s failed: host lookup", aconf->name);
+ sendto_opmask_butone(0, SNO_OLDSNO, "Connect to %s failed: host lookup",
+ aconf->name);
}
+/*
+ * close_connections - closes all connections
+ * close stderr if specified
+ */
+void close_connections(int close_stderr)
+{
+ int i;
+ close(0);
+ close(1);
+ if (close_stderr)
+ close(2);
+ for (i = 3; i < MAXCONNECTIONS; ++i)
+ close(i);
+}
+
+/*
+ * init_connection_limits - initialize process fd limit to
+ * MAXCONNECTIONS
+ */
+int init_connection_limits(void)
+{
+ int limit = os_set_fdlimit(MAXCONNECTIONS);
+ if (0 == limit)
+ return 1;
+ if (limit < 0) {
+ fprintf(stderr, "error setting max fd's to %d\n", limit);
+ }
+ else if (limit > 0) {
+ fprintf(stderr, "ircd fd table too big\nHard Limit: %d IRC max: %d\n",
+ limit, MAXCONNECTIONS);
+ fprintf(stderr, "set MAXCONNECTIONS to a smaller value");
+ }
+ return 0;
+}
/*
* connect_inet - set up address and port and make a connection
* explicitly bind it, it will default to IN_ADDR_ANY and we lose
* due to the other server not allowing our base IP --smg
*/
- if (bind(cptr->fd, (struct sockaddr*) &virtualHost, sizeof(virtualHost))) {
+ if (bind(cptr->fd, (struct sockaddr*) &VirtualHost, sizeof(VirtualHost))) {
report_error(BIND_ERROR_MSG, cptr->name, errno);
return 0;
}
* net.loads today anyway. Commented out the alarms to save cpu.
* --Run
*/
-size_t deliver_it(struct Client *cptr, const char *str, size_t len)
+unsigned int deliver_it(struct Client *cptr, const char *str, unsigned int len)
{
- size_t bytes_written = 0;
+ unsigned int bytes_written = 0;
assert(0 != cptr);
switch (os_send_nonb(cptr->fd, str, len, &bytes_written)) {
return bytes_written;
}
-/*
- * init_sys
- */
-void init_sys(void)
-{
- int fd;
- int limit = os_set_fdlimit(MAXCONNECTIONS);
- if (limit < 0) {
- fprintf(stderr, "error setting max fd's to %d\n", limit);
- exit(2);
- }
- else if (limit > 0) {
- fprintf(stderr, "ircd fd table too big\nHard Limit: %d IRC max: %d\n",
- limit, MAXCONNECTIONS);
- fprintf(stderr, "set MAXCONNECTIONS to a smaller value");
- exit(2);
- }
-
- for (fd = 3; fd < MAXCONNECTIONS; ++fd)
- {
- close(fd);
- LocalClientArray[fd] = NULL;
- }
- LocalClientArray[2] = 0;
- LocalClientArray[1] = 0;
- LocalClientArray[0] = 0;
- close(1);
- close(0);
-
- if (bootopt & BOOT_TTY) {
- /* debugging is going to a tty */
- init_resolver();
- return;
- }
- if (!(bootopt & BOOT_DEBUG))
- close(2);
-
- if (fork())
- exit(0);
- running_in_background = 1;
-#ifdef TIOCNOTTY
- if ((fd = open("/dev/tty", O_RDWR)) > -1) {
- ioctl(fd, TIOCNOTTY, 0);
- close(fd);
- }
-#endif
- setsid();
- init_resolver();
-}
void release_dns_reply(struct Client* cptr)
{
* connection actually succeeded
*/
if ((cptr->error = os_get_sockerr(cptr->fd))) {
- sendto_ops("Connection failed to %s: %s", cptr->name,
- strerror(cptr->error));
+ const char* msg = strerror(cptr->error);
+ if (!msg)
+ msg = "Unknown error";
+ sendto_opmask_butone(0, SNO_OLDSNO, "Connection failed to %s: %s",
+ cptr->name, msg);
return 0;
}
if (!(aconf = find_conf_byname(cptr->confs, cptr->name, CONF_SERVER))) {
- sendto_ops("Lost Server Line for %s", cptr->name);
+ sendto_opmask_butone(0, SNO_OLDSNO, "Lost Server Line for %s", cptr->name);
return 0;
}
+
if (!EmptyString(aconf->passwd))
- sendto_one(cptr, "PASS :%s", aconf->passwd);
+ sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);
#if 0
/* dead code, already done in connect_server */
*/
cptr->lasttime = CurrentTime;
cptr->flags |= FLAGS_PINGSENT;
- sendto_one(cptr, "SERVER %s 1 " TIME_T_FMT " " TIME_T_FMT " J%s %s%s :%s",
- me.name, me.serv->timestamp, newts, MAJOR_PROTOCOL,
- NumServCap(&me), me.info);
+
+ sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s :%s",
+ me.name, me.serv->timestamp, newts, MAJOR_PROTOCOL,
+ NumServCap(&me), me.info);
return (IsDead(cptr)) ? 0 : 1;
}
for (i = HighestFd; i > 0; --i) {
if ((cptr = LocalClientArray[i]) && !IsRegistered(cptr)) {
- sendto_one(source, rpl_str(RPL_CLOSING), me.name, source->name,
- get_client_name(source, HIDE_IP), cptr->status);
+ send_reply(source, RPL_CLOSING, get_client_name(source, HIDE_IP));
exit_client(source, cptr, &me, "Oper Closing");
++count;
}
return count;
}
-/*
+/*----------------------------------------------------------------------------
+ * add_connection
+ *
* Creates a client which has just connected to us on the given fd.
* The sockhost field is initialized with the ip# of the host.
* The client is not added to the linked list of clients, it is
* passed off to the auth handler for dns and ident queries.
- */
-void add_connection(struct Listener* listener, int fd)
-{
+ *--------------------------------------------------------------------------*/
+void add_connection(struct Listener* listener, int fd) {
struct sockaddr_in addr;
- struct Client* new_client;
+ struct Client *new_client;
time_t next_target = 0;
+
const char* const throttle_message =
"ERROR: Your host is trying to (re)connect too fast -- throttled\r\n";
/* 12345678901234567890123456789012345679012345678901234567890123456 */
assert(0 != listener);
+
/*
- * Removed preliminary access check. Full check is performed in
- * m_server and m_user instead. Also connection time out help to
- * get rid of unwanted connections.
+ * Removed preliminary access check. Full check is performed in m_server and
+ * m_user instead. Also connection time out help to get rid of unwanted
+ * connections.
*/
if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
++ServerStats->is_ref;
close(fd);
return;
}
- /*
- * XXX - do we really want to do this? is it needed?
- */
- os_disable_options(fd);
+
/*
* Add this local client to the IPcheck registry.
+ *
* If it is a connection to a user port and if the site has been throttled,
* reject the user.
*/
- if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server) {
- ++ServerStats->is_ref;
- /*
- * strlen(throttle_message) == 66
- */
+ if (!ip_registry_check_local(addr.sin_addr.s_addr, &next_target) &&
+ !listener->server) {
send(fd, throttle_message, 66, 0);
close(fd);
+ ++ServerStats->is_ref;
return;
}
- new_client = make_client(NULL,
- (listener->server) ? STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER);
+ new_client = make_client(0, ((listener->server) ?
+ STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER));
+
+ if (!listener->server)
+ ip_registry_local_connect(new_client);
+
/*
- * Copy ascii address to 'sockhost' just in case. Then we
- * have something valid to put into error messages...
+ * Copy ascii address to 'sockhost' just in case. Then we have something
+ * valid to put into error messages...
*/
ircd_ntoa_r(new_client->sock_ip, (const char*) &addr.sin_addr);
strcpy(new_client->sockhost, new_client->sock_ip);
new_client->nexttarget = next_target;
new_client->fd = fd;
-
- if (!listener->server)
- SetIPChecked(new_client);
new_client->listener = listener;
++listener->ref_count;
Count_newunknown(UserStats);
- /*
- * if we've made it this far we can put the client on the auth query pile
- */
+
+ /* if we've made it this far we can put the client on the auth query pile */
start_auth(new_client);
}
+
/*
* read_packet
*
*/
static int read_packet(struct Client *cptr, int socket_ready)
{
- size_t dolen = 0;
- size_t length = 0;
+ unsigned int dolen = 0;
+ unsigned int length = 0;
if (socket_ready && !(IsUser(cptr) && DBufLength(&cptr->recvQ) > CLIENT_FLOOD)) {
switch (os_recv_nonb(cptr->fd, readbuf, sizeof(readbuf), &length)) {
int read_message(time_t delay)
{
struct pollfd poll_fds[MAXCONNECTIONS + 1];
- struct Client* cptr;
- struct Listener* listener = 0;
- struct AuthRequest* auth = 0;
- struct AuthRequest* auth_next = 0;
- int nfds;
+ struct Client* cptr;
+ struct Listener* listener = 0;
+ struct AuthRequest* auth = 0;
+ struct AuthRequest* auth_next = 0;
+ struct UPing* uping = 0;
+ struct UPing* uping_next = 0;
time_t delay2 = delay;
+ int nfds;
int length;
int i;
int res = 0;
- int pfd_count = 0;
- struct pollfd* pfd = 0;
- struct pollfd* res_pfd = 0;
+ int pfd_count;
+ struct pollfd* pfd;
+ struct pollfd* res_pfd;
+ struct pollfd* uping_pfd;
int read_ready;
int write_ready;
- unsigned long timeout;
+ unsigned int timeout;
for ( ; ; ) {
pfd_count = 0;
pfd = poll_fds;
res_pfd = 0;
+ uping_pfd = 0;
pfd->fd = -1;
if (-1 < ResolverFileDescriptor) {
PFD_SETR(ResolverFileDescriptor);
res_pfd = pfd;
}
+ if (-1 < UPingFileDescriptor) {
+ PFD_SETR(UPingFileDescriptor);
+ uping_pfd = pfd;
+ }
+ /*
+ * add uping descriptors
+ */
+ for (uping = uping_begin(); uping; uping = uping_next) {
+ uping_next = uping->next;
+ if (uping->active) {
+ delay2 = 1;
+ if (uping->lastsent && CurrentTime > uping->timeout) {
+ uping_end(uping);
+ continue;
+ }
+ uping->index = pfd_count;
+ PFD_SETR(uping->fd);
+ }
+ }
/*
* add auth file descriptors
*/
CurrentTime = time(0);
}
+ if (uping_pfd && (uping_pfd->revents & (POLLREADFLAGS | POLLERRORS))) {
+ uping_echo();
+ --nfds;
+ }
+ /*
+ * check uping replies
+ */
+ for (uping = uping_begin(); uping; uping = uping_next) {
+ uping_next = uping->next;
+ if (uping->active) {
+ assert(-1 < uping->index);
+ if (poll_fds[uping->index].revents) {
+ uping_read(uping);
+ if (0 == --nfds)
+ break;
+ }
+ else if (CurrentTime > uping->lastsent) {
+ uping->lastsent = CurrentTime;
+ uping_send(uping);
+ }
+ }
+ }
+
if (res_pfd && (res_pfd->revents & (POLLREADFLAGS | POLLERRORS))) {
resolver_read();
--nfds;
}
if (write_ready) {
if (!on_write_unblocked(cptr) || IsDead(cptr)) {
- exit_client(cptr, cptr, &me,
- cptr->error ? strerror(cptr->error) : LastDeadComment(cptr));
+ const char* msg = (cptr->error) ? strerror(cptr->error) : cptr->info;
+ if (!msg)
+ msg = "Unknown error";
+ exit_client(cptr, cptr, &me, msg);
continue;
}
}
flush_connections(poll_cptr[i]);
#endif
if (IsDead(cptr)) {
- exit_client(cptr, cptr, &me,
- cptr->error ? strerror(cptr->error) : LastDeadComment(cptr));
+ const char* msg = (cptr->error) ? strerror(cptr->error) : cptr->info;
+ if (!msg)
+ msg = "Unknown error";
+ exit_client(cptr, cptr, &me, (char*) msg);
continue;
}
if (length > 0)
if ((IsServer(cptr) || IsHandshake(cptr)) && cptr->error == 0 && length == 0)
exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)",
cptr->name, cptr->serv->last_error_msg);
- else
- exit_client_msg(cptr, cptr, &me, "Read error to %s: %s",
- get_client_name(cptr, HIDE_IP),
- (cptr->error) ? strerror(cptr->error) : "EOF from client");
+ else {
+ const char* msg = (cptr->error) ? strerror(cptr->error) : "EOF from client";
+ if (!msg)
+ msg = "Unknown error";
+ exit_client_msg(cptr, cptr, &me, "Read error: %s",
+ msg);
+ }
}
return 0;
}
{
struct Client* cptr;
struct Listener* listener;
+ struct AuthRequest* auth = 0;
+ struct AuthRequest* auth_next = 0;
+ struct UPing* uping;
+ struct UPing* uping_next;
int nfds;
struct timeval wait;
time_t delay2 = delay;
- unsigned long usec = 0;
+ unsigned int usec = 0;
int res = 0;
int length;
int i;
- struct AuthRequest* auth = 0;
- struct AuthRequest* auth_next = 0;
int read_ready;
fd_set read_set;
fd_set write_set;
if (-1 < ResolverFileDescriptor)
FD_SET(ResolverFileDescriptor, &read_set);
+ if (-1 < UPingFileDescriptor)
+ FD_SET(UPingFileDescriptor, &read_set);
+ /*
+ * set up uping file descriptors
+ */
+ for (uping = uping_begin(); uping; uping = uping_next) {
+ uping_next = uping->next;
+ if (uping->active) {
+ delay2 = 1;
+ if (uping->lastsent && CurrentTime > uping->timeout) {
+ uping_end(uping);
+ continue;
+ }
+ assert(-1 < uping->fd);
+ FD_SET(uping->fd, &read_set);
+ }
+ }
/*
* set auth file descriptors
*/
CurrentTime = time(0);
}
- if (-1 < ResolverFileDescriptor &&
- FD_ISSET(ResolverFileDescriptor, &read_set)) {
+ if (-1 < UPingFileDescriptor && FD_ISSET(UPingFileDescriptor, &read_set)) {
+ uping_echo();
+ --nfds;
+ }
+ for (uping = uping_begin(); uping; uping = uping_next) {
+ uping_next = uping->next;
+ if (uping->active) {
+ assert(-1 < uping->fd);
+ if (FD_ISSET(uping->fd, &read_set)) {
+ uping_read(uping);
+ if (0 == --nfds)
+ break;
+ }
+ else if (CurrentTime > uping->lastsent) {
+ uping->lastsent = CurrentTime;
+ uping_send(uping);
+ }
+ }
+ }
+ if (-1 < ResolverFileDescriptor && FD_ISSET(ResolverFileDescriptor, &read_set)) {
resolver_read();
--nfds;
}
if (FD_ISSET(i, &write_set)) {
--nfds;
if (!on_write_unblocked(cptr) || IsDead(cptr)) {
+ const char* msg = (cptr->error) ? strerror(cptr->error) : cptr->info;
+ if (!msg)
+ msg = "Unknown error";
if (FD_ISSET(i, &read_set))
--nfds;
- exit_client(cptr, cptr, &me,
- cptr->error ? strerror(cptr->error) : LastDeadComment(cptr));
+ exit_client(cptr, cptr, &me, msg);
continue;
}
}
flush_connections(LocalClientArray[i]);
#endif
if (IsDead(cptr)) {
- exit_client(cptr, cptr, &me,
- cptr->error ? strerror(cptr->error) : LastDeadComment(cptr));
+ const char* msg = (cptr->error) ? strerror(cptr->error) : cptr->info;
+ if (!msg)
+ msg = "Unknown error";
+ exit_client(cptr, cptr, &me, msg);
continue;
}
if (length > 0)
if ((IsServer(cptr) || IsHandshake(cptr)) && cptr->error == 0 && length == 0)
exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)",
cptr->name, cptr->serv->last_error_msg);
- else
- exit_client_msg(cptr, cptr, &me, "Read error to %s: %s",
- get_client_name(cptr, HIDE_IP),
- cptr->error ? strerror(cptr->error) : "EOF from client");
+ else {
+ const char* msg = (cptr->error) ? strerror(cptr->error) : "EOF from client";
+ if (!msg)
+ msg = "Unknown error";
+ exit_client_msg(cptr, cptr, &me, "Read error: %s",
+ msg);
+ }
}
return 0;
}
assert(0 != aconf);
if (aconf->dns_pending) {
- sendto_ops("Server %s connect DNS pending");
+ sendto_opmask_butone(0, SNO_OLDSNO, "Server %s connect DNS pending",
+ aconf->name);
return 0;
}
Debug((DEBUG_NOTICE, "Connect to %s[@%s]", aconf->name,
if ((cptr = FindClient(aconf->name))) {
if (IsServer(cptr) || IsMe(cptr)) {
- sendto_ops("Server %s already present from %s",
- aconf->name, cptr->from->name);
+ sendto_opmask_butone(0, SNO_OLDSNO, "Server %s already present from %s",
+ aconf->name, cptr->from->name);
if (by && IsUser(by) && !MyUser(by)) {
- sendto_one(by, "%s NOTICE %s%s :Server %s already present from %s",
- NumServ(&me), NumNick(by), aconf->name, cptr->from->name);
+ sendcmdto_one(&me, CMD_NOTICE, by, "%C :Server %s already present "
+ "from %s", by, aconf->name, cptr->from->name);
}
return 0;
}
else if (IsHandshake(cptr) || IsConnecting(cptr)) {
if (by && IsUser(by)) {
- if (MyUser(by))
- sendto_one(by, ":%s NOTICE %s :Connection to %s already in progress",
- me.name, by->name, cptr->name);
- else
- sendto_one(by, "%s NOTICE %s%s :Connection to %s already in progress",
- NumServ(&me), NumNick(by), cptr->name);
+ sendcmdto_one(&me, CMD_NOTICE, by, "%C :Connection to %s already in "
+ "progress", by, cptr->name);
}
return 0;
}
attach_confs_byhost(cptr, aconf->host, CONF_SERVER);
if (!find_conf_byhost(cptr->confs, aconf->host, CONF_SERVER)) {
- sendto_ops("Host %s is not enabled for connecting: no C-line", aconf->name);
+ sendto_opmask_butone(0, SNO_OLDSNO, "Host %s is not enabled for "
+ "connecting: no C-line", aconf->name);
if (by && IsUser(by) && !MyUser(by)) {
- sendto_one(by, "%s NOTICE %s%s :Connect to host %s failed: no C-line",
- NumServ(&me), NumNick(by), aconf->name);
+ sendcmdto_one(&me, CMD_NOTICE, by, "%C :Connect to host %s failed: no "
+ "C-line", by, aconf->name);
}
det_confs_butmask(cptr, 0);
free_client(cptr);
*/
if (!connect_inet(aconf, cptr)) {
if (by && IsUser(by) && !MyUser(by)) {
- sendto_one(by, "%s NOTICE %s%s :Couldn't connect to %s",
- NumServ(&me), NumNick(by), cptr->name);
+ sendcmdto_one(&me, CMD_NOTICE, by, "%C :Couldn't connect to %s", by,
+ cptr->name);
}
det_confs_butmask(cptr, 0);
free_client(cptr);
{
assert(0 != conf);
- memset(&virtualHost, 0, sizeof(virtualHost));
- virtualHost.sin_family = AF_INET;
- virtualHost.sin_addr.s_addr = INADDR_ANY;
+ memset(&VirtualHost, 0, sizeof(VirtualHost));
+ VirtualHost.sin_family = AF_INET;
+ VirtualHost.sin_addr.s_addr = INADDR_ANY;
if (EmptyString(conf->passwd) || 0 == strcmp(conf->passwd, "*"))
return;
- virtualHost.sin_addr.s_addr = inet_addr(conf->passwd);
+ VirtualHost.sin_addr.s_addr = inet_addr(conf->passwd);
- if (INADDR_NONE == virtualHost.sin_addr.s_addr)
- virtualHost.sin_addr.s_addr = INADDR_ANY;
+ if (INADDR_NONE == VirtualHost.sin_addr.s_addr)
+ VirtualHost.sin_addr.s_addr = INADDR_ANY;
}
/*