]> jfr.im git - irc/quakenet/newserv.git/blobdiff - nterface/nterfacer.c
Sigh
[irc/quakenet/newserv.git] / nterface / nterfacer.c
index 9db5d424a0a523a10251a5c252b23b7243d23880..6af51996a6dd9efd684d9a5e8a870b932c16a6f4 100644 (file)
@@ -1,7 +1,15 @@
 /*
   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;
@@ -40,6 +52,10 @@ struct rline *rlines = NULL;
 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);
@@ -60,6 +76,13 @@ void _init(void) {
 
   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!");
@@ -71,14 +94,18 @@ void _init(void) {
   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;
@@ -88,6 +115,9 @@ void _fini(void) {
   struct service_node *tp, *lp;
   int i;
 
+  if(ping)
+    deregister_service(ping);
+
   for(tp=tree;tp;) {
     lp = tp;
     tp = tp->next;
@@ -121,7 +151,7 @@ int load_permits(void) {
   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;
@@ -135,7 +165,7 @@ int load_permits(void) {
     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;
     }
 
@@ -162,7 +192,7 @@ int load_permits(void) {
     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;
     }
@@ -211,7 +241,7 @@ int setup_listening_socket(void) {
   /* 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);
@@ -220,7 +250,7 @@ int setup_listening_socket(void) {
   
   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;
   }
@@ -257,15 +287,32 @@ struct handler *register_handler(struct service_node *service, char *command, in
     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;
@@ -313,12 +360,18 @@ void nterfacer_accept_event(struct esocket *socket) {
   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];
@@ -386,7 +439,9 @@ int nterfacer_line_event(struct esocket *sock, char *newline) {
           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:
@@ -417,7 +472,7 @@ int nterfacer_line_event(struct esocket *sock, char *newline) {
         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);
@@ -429,8 +484,12 @@ int nterfacer_line_event(struct esocket *sock, char *newline) {
       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;
         }
@@ -442,7 +501,7 @@ int nterfacer_line_event(struct esocket *sock, char *newline) {
 }
 
 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;
@@ -542,7 +601,7 @@ int nterfacer_new_rline(char *line, struct esocket *socket, int *number) {
     *newp = '\0';
   }
   if(argcount < hl->args) {
-    if(argcount)
+    if(argcount && parsebuf)
       free(parsebuf);
     return RE_WRONG_ARG_COUNT;
   }
@@ -550,13 +609,14 @@ int nterfacer_new_rline(char *line, struct esocket *socket, int *number) {
   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;
@@ -564,9 +624,9 @@ int nterfacer_new_rline(char *line, struct esocket *socket, int *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;
@@ -624,6 +684,7 @@ int ri_error(struct rline *li, int error_code, char *format, ...) {
   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);
@@ -634,7 +695,8 @@ int ri_error(struct rline *li, int error_code, char *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) {
@@ -649,15 +711,17 @@ int ri_error(struct rline *li, int error_code, char *format, ...) {
     }
   }
   
-  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) {
@@ -670,5 +734,10 @@ int ri_final(struct rline *li) {
     }
   }
 
-  return RE_OK;
+  return retval;
+}
+
+int ping_handler(struct rline *ri, int argc, char **argv) {
+  ri_append(ri, "OK");
+  return ri_final(ri);
 }