/*
nterfacer
- Copyright (C) 2004 Chris Porter.
+ Copyright (C) 2004-2006 Chris Porter.
+ v1.07a
+ - dumb config bug
+ v1.07
+ - made sure buf[0] = '\0'
+ v1.06
+ - tidy up
+ v1.05
+ - added application level ping support
v1.04
- modified for new logging system
v1.03
#include <sys/ioctl.h>
#include <netdb.h>
#include <string.h>
+#include <strings.h>
#include "../lib/sstring.h"
#include "../lib/irc_string.h"
#include "../core/config.h"
#include "../core/events.h"
+#include "../lib/version.h"
#include "nterfacer.h"
#include "logging.h"
+MODULE_VERSION("$Id: nterfacer.c 663 2006-05-16 17:27:36Z newserv $")
+
struct service_node *tree = NULL;
struct esocket_events nterfacer_events;
struct esocket *nterfacer_sock;
unsigned short nterfacer_token = BLANK_TOKEN;
struct nterface_auto_log *nrl;
+struct service_node *ping = NULL;
+
+int ping_handler(struct rline *ri, int argc, char **argv);
+
void _init(void) {
int loaded;
int debug_mode = getcopyconfigitemintpositive("nterfacer", "debug", 0);
nterfacer_token = esocket_token();
+ ping = register_service("nterfacer");
+ if(!ping) {
+ MemError();
+ } else {
+ register_handler(ping, "ping", 0, ping_handler);
+ }
+
accept_fd = setup_listening_socket();
if(accept_fd == -1) {
nterface_log(nrl, NL_ERROR, "Unable to setup listening socket!");
nterfacer_events.on_disconnect = nterfacer_disconnect_event;
}
+void free_handler(struct handler *hp) {
+ freesstring(hp->command);
+ free(hp);
+}
+
void free_handlers(struct service_node *tp) {
struct handler *hp, *lp;
for(hp=tp->handlers;hp;) {
lp = hp;
hp = hp->next;
- freesstring(lp->command);
- free(lp);
+ free_handler(lp);
}
tp->handlers = NULL;
struct service_node *tp, *lp;
int i;
+ if(ping)
+ deregister_service(ping);
+
for(tp=tree;tp;) {
lp = tp;
tp = tp->next;
struct hostent *host;
char buf[50];
- lines = getcopyconfigitemintpositive("nterfacer", "lines", 0);
+ lines = getcopyconfigitemintpositive("nterfacer", "permits", 0);
if(lines < 1) {
nterface_log(nrl, NL_ERROR, "No permits found in config file.");
return 0;
snprintf(buf, sizeof(buf), "hostname%d", i);
item->hostname = getcopyconfigitem("nterfacer", buf, "", 100);
if(!item->hostname) {
- MemError();
+ nterface_log(nrl, NL_ERROR, "No hostname found for item %d.", i);
continue;
}
snprintf(buf, sizeof(buf), "password%d", i);
item->password = getcopyconfigitem("nterfacer", buf, "", 100);
if(!item->password) {
- MemError();
+ nterface_log(nrl, NL_ERROR, "No password found for item %d.", item->hostname->content, i);
freesstring(item->hostname);
continue;
}
/* Initialiase the addresses */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
- sin.sin_port = htons(NTERFACER_PORT);
+ sin.sin_port = htons(getcopyconfigitemintpositive("nterfacer", "port", NTERFACER_PORT));
if(bind(fd, (struct sockaddr *) &sin, sizeof(sin))) {
nterface_log(nrl, NL_ERROR, "Unable to bind listen socket (%d).", errno);
listen(fd, 5);
- if(ioctl(fd, FIONBIO, &opt) !=0) {
+ if(ioctl(fd, FIONBIO, &opt)) {
nterface_log(nrl, NL_ERROR, "Unable to set listen socket non-blocking.");
return -1;
}
return NULL;
}
- hp->function = (handler_function *)fp;
+ hp->function = fp;
hp->args = args;
hp->next = service->handlers;
+ hp->service = service;
service->handlers = hp;
return hp;
}
+void deregister_handler(struct handler *hl) {
+ struct service_node *service = (struct service_node *)hl->service;
+ struct handler *np, *lp = NULL;
+ for(np=service->handlers;np;lp=np,np=np->next) {
+ if(hl == np) {
+ if(lp) {
+ lp->next = np->next;
+ } else {
+ service->handlers = np->next;
+ }
+ free_handler(np);
+ return;
+ }
+ }
+}
+
void deregister_service(struct service_node *service) {
struct service_node *sp, *lp = NULL;
struct rline *li, *pi = NULL;
struct sconnect *temp;
struct permitted *item = NULL;
struct esocket *newsocket;
+ unsigned int opt = 1;
if(newfd == -1) {
nterface_log(nrl, NL_WARNING, "Unable to accept nterfacer fd!");
return;
}
+ if(ioctl(newfd, FIONBIO, &opt)) {
+ nterface_log(nrl, NL_ERROR, "Unable to set accepted socket non-blocking.");
+ return;
+ }
+
for(i=0;i<permit_count;i++) {
if(permits[i].ihost == sin.sin_addr.s_addr) {
item = &permits[i];
return 1;
}
- return esocket_write_line(sock, "%s %s", hex, int_to_hex(socket->ournonce, hexbuf, NONCE_LEN));
+ if(esocket_write_line(sock, "%s %s", hex, int_to_hex(socket->ournonce, hexbuf, NONCE_LEN)))
+ return BUF_ERROR;
+ return 0;
}
break;
case SS_VERSIONED:
if(!ret) {
switch_buffer_mode(sock, socket->permit->password->content, socket->ournonce, theirnonce);
} else {
- return ret;
+ return BUF_ERROR;
}
} else {
nterface_log(nrl, NL_INFO, "Bad CR drop: %s", socket->permit->hostname->content);
nterface_log(nrl, NL_INFO|NL_LOG_ONLY, "L(%s): %s", socket->permit->hostname->content, newline);
reason = nterfacer_new_rline(newline, sock, &number);
if(reason) {
+ if(reason == RE_SOCKET_ERROR)
+ return BUF_ERROR;
if(reason != RE_BAD_LINE) {
- return esocket_write_line(sock, "%d,E%d,%s", number, reason, request_error(reason));
+ if(esocket_write_line(sock, "%d,E%d,%s", number, reason, request_error(reason)))
+ return BUF_ERROR;
+ return 0;
} else {
return 1;
}
}
int nterfacer_new_rline(char *line, struct esocket *socket, int *number) {
- char *sp, *p, *parsebuf, *pp, commandbuf[MAX_BUFSIZE], *args[MAX_ARGS], *newp;
+ char *sp, *p, *parsebuf = NULL, *pp, commandbuf[MAX_BUFSIZE], *args[MAX_ARGS], *newp;
int argcount;
struct service_node *service;
struct rline *prequest;
*newp = '\0';
}
if(argcount < hl->args) {
- if(argcount)
+ if(argcount && parsebuf)
free(parsebuf);
return RE_WRONG_ARG_COUNT;
}
prequest = (struct rline *)malloc(sizeof(struct rline));
if(!prequest) {
MemError();
- if(argcount)
+ if(argcount && parsebuf)
free(parsebuf);
return RE_MEM_ERROR;
}
prequest->service = service;
prequest->handler = hl;
+ prequest->buf[0] = '\0';
prequest->curpos = prequest->buf;
prequest->tag = NULL;
prequest->id = *number;
prequest->socket = socket;
rlines = prequest;
- re = ((handler_function)hl->function)(prequest, argcount, args);
+ re = (hl->function)(prequest, argcount, args);
- if(argcount)
+ if(argcount && parsebuf)
free(parsebuf);
return re;
char buf[MAX_BUFSIZE], escapedbuf[MAX_BUFSIZE * 2 + 1], *p, *tp;
struct rline *pp, *lp = NULL;
va_list ap;
+ int retval = RE_OK;
if(li->socket) {
va_start(ap, format);
if((*p == ',') || (*p == '\\'))
*tp++ = '\\';
- esocket_write_line(li->socket, "%d,OE%d,%s", li->id, error_code, escapedbuf);
+ if(esocket_write_line(li->socket, "%d,OE%d,%s", li->id, error_code, escapedbuf))
+ retval = RE_SOCKET_ERROR;
}
for(pp=rlines;pp;lp=pp,pp=pp->next) {
}
}
- return RE_OK;
+ return retval;
}
int ri_final(struct rline *li) {
struct rline *pp, *lp = NULL;
+ int retval = RE_OK;
if(li->socket)
- esocket_write_line(li->socket, "%d,OO%s", li->id, li->buf);
-
+ if(esocket_write_line(li->socket, "%d,OO%s", li->id, li->buf))
+ retval = RE_SOCKET_ERROR;
+
for(pp=rlines;pp;lp=pp,pp=pp->next) {
if(pp == li) {
if(lp) {
}
}
- return RE_OK;
+ return retval;
+}
+
+int ping_handler(struct rline *ri, int argc, char **argv) {
+ ri_append(ri, "OK");
+ return ri_final(ri);
}