]> jfr.im git - irc/quakenet/newserv.git/blobdiff - trusts/trusts_policy.c
TRUSTS: turn on tcpkeepalive for trust policy sockets.
[irc/quakenet/newserv.git] / trusts / trusts_policy.c
index 663007518c67ae2ed6146179215dd031e9cbff99..b5c70d8e9642b0172d7342b0c53e8ef40280889b 100644 (file)
@@ -5,6 +5,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 
 #ifndef __USE_MISC
 #define __USE_MISC /* inet_aton */
@@ -49,6 +50,7 @@ typedef struct trustsocket {
   time_t timeout;
   int accepted;
   int rejected;
+  int unthrottled;
 
   struct trustsocket *next;
 } trustsocket;
@@ -166,7 +168,7 @@ static int checkconnection(const char *username, struct irc_in_addr *ipaddress,
     snprintf(message, messagelen, "Trust has %d out of %d allowed connections.", tg->count + usercountadjustment, tg->trustedfor);
 
   if(unthrottle && (tg->flags & TRUST_UNTHROTTLE))
-    *unthrottle = 1; /* TODO: Do _some_ kind of rate-limiting */
+    *unthrottle = 1;
 
   return POLICY_SUCCESS;
 }
@@ -195,8 +197,7 @@ static int policycheck_auth(trustsocket *sock, const char *sequence_id, const ch
   int verdict, unthrottle;
   struct irc_in_addr ipaddress;
   unsigned char bits;
-  trustsocket *ts;
-  
+
   if(!ipmask_parse(host, &ipaddress, &bits)) {
     sock->accepted++;
     return trustdowrite(sock, "PASS %s", sequence_id);
@@ -211,8 +212,8 @@ static int policycheck_auth(trustsocket *sock, const char *sequence_id, const ch
     sock->accepted++;
 
     if (unthrottle) {
-      for (ts = tslist; ts; ts = ts->next)
-        trustdowrite(ts, "UNTHROTTLE %s", IPtostr(ipaddress));
+      sock->unthrottled++;
+      trustdowrite(sock, "UNTHROTTLE %s", sequence_id);
     }
 
     if(message[0])
@@ -243,9 +244,8 @@ static void trustfreeconnection(trustsocket *sock, int unlink) {
     return;
   }
 
-  pnext = &tslist;
-  
-  for(ts=*pnext;*pnext;pnext=&((*pnext)->next)) {
+  for(pnext=&tslist;*pnext;pnext=&((*pnext)->next)) {
+    ts=*pnext;
     if(ts == sock) {
       *pnext = sock->next;
       trustfreeconnection(sock, 0);
@@ -260,6 +260,7 @@ static int handletrustauth(trustsocket *sock, char *server_name, char *mac) {
   unsigned char digest[16];
   char noncehexbuf[NONCELEN * 2 + 1];
   char hexbuf[sizeof(digest) * 2 + 1];
+  trustsocket *ts, **pnext;
 
   for(i=0;i<MAXSERVERS;i++) {
     if(trustaccounts[i].used && strcmp(trustaccounts[i].server, server_name) == 0) {
@@ -282,6 +283,16 @@ static int handletrustauth(trustsocket *sock, char *server_name, char *mac) {
     return trustkillconnection(sock, "Bad MAC.");
   }
 
+  for(pnext=&tslist;*pnext;pnext=&((*pnext)->next)) {
+    ts = *pnext;
+    if(ts->authed && strcmp(ts->authuser, server_name) == 0) {
+      trustkillconnection(ts, "New connection with same server name.");
+      *pnext = ts->next;
+      trustfreeconnection(ts, 0);
+      break;
+    }
+  }
+
   sock->authed = 1;
   strncpy(sock->authuser, server_name, SERVERLEN);
 
@@ -394,9 +405,8 @@ static void trustdotimeout(void *arg) {
   time_t t = time(NULL);
   trustsocket **pnext, *sock;
 
-  pnext = &tslist;
-    
-  for(sock=*pnext;*pnext;pnext=&((*pnext)->next)) {
+  for(pnext=&tslist;*pnext;pnext=&((*pnext)->next)) {
+    sock = *pnext;
     if(!sock->authed && t >= sock->timeout) {
       trustkillconnection(sock, "Auth timeout.");
       *pnext = sock->next;
@@ -409,6 +419,7 @@ static void processtrustlistener(int fd, short events) {
   if(events & POLLIN) {
     trustsocket *sock;
     char buf[NONCELEN * 2 + 1];
+    int optval;
 
     int newfd = accept(fd, NULL, NULL), flags;
     if(newfd == -1)
@@ -427,6 +438,15 @@ static void processtrustlistener(int fd, short events) {
       return;
     }
 
+    optval = 10;
+    setsockopt(newfd, SOL_SOCKET, TCP_KEEPIDLE, &optval, sizeof(optval));
+    optval = 3;
+    setsockopt(newfd, SOL_SOCKET, TCP_KEEPCNT, &optval, sizeof(optval));
+    optval = 10;
+    setsockopt(newfd, SOL_SOCKET, TCP_KEEPINTVL, &optval, sizeof(optval));
+    optval = 1;
+    setsockopt(newfd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval));
+
     registerhandler(newfd, POLLIN|POLLERR|POLLHUP, processtrustclient);
       
     sock = nsmalloc(POOL_TRUSTS, sizeof(trustsocket));
@@ -451,6 +471,7 @@ static void processtrustlistener(int fd, short events) {
       sock->timeout = time(NULL) + 30;
       sock->accepted = 0;
       sock->rejected = 0;
+      sock->unthrottled = 0;
       if(!trustdowrite(sock, "AUTH %s", hmac_printhex(sock->nonce, buf, NONCELEN))) {
         Error("trusts_policy", ERR_WARNING, "Error writing auth to fd %d.", newfd);
         deregisterhandler(newfd, 1);
@@ -504,7 +525,6 @@ static void policycheck_irc(int hooknum, void *arg) {
   long moving = (long)args[1];
   char message[512];
   int verdict, unthrottle;
-  trustsocket *ts;
 
   if(moving)
     return;
@@ -526,10 +546,6 @@ static void policycheck_irc(int hooknum, void *arg) {
       break;
   }
 
-  if (unthrottle && hooknum == HOOK_NICK_LOSTNICK && np->timestamp > getnettime() - TRUST_MIN_TIME_RETHROTTLE) {
-    for (ts = tslist; ts; ts = ts->next)
-      trustdowrite(ts, "THROTTLE %s", IPtostr(np->ipaddress));
-  }
 }
 
 static int trusts_cmdtrustpolicyirc(void *source, int cargc, char **cargv) {
@@ -570,10 +586,10 @@ static int trusts_cmdtrustsockets(void *source, int cargc, char **cargv) {
 
   time(&now);
 
-  controlreply(sender, "Server                              Connected for        Accepted        Rejected");
+  controlreply(sender, "Server                              Connected for        Accepted        Rejected        Unthrottled");
 
   for(sock=tslist;sock;sock=sock->next)
-    controlreply(sender, "%-35s %-20s %-15d %-15d", sock->authed?sock->authuser:"<unauthenticated connection>", longtoduration(now - sock->connected, 0), sock->accepted, sock->rejected);
+    controlreply(sender, "%-35s %-20s %-15d %-15d %-15d", sock->authed?sock->authuser:"<unauthenticated connection>", longtoduration(now - sock->connected, 0), sock->accepted, sock->rejected, sock->unthrottled);
 
   controlreply(sender, "-- End of list.");
   return CMD_OK;