]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - src/listener.c
listener.c fixes - part 1
[irc/rqf/shadowircd.git] / src / listener.c
index d3ceb2ae28d42424487361619a5197fd39ae532f..8ac2c8b9d316c10518247bea2899d5f81fc939d5 100644 (file)
@@ -52,6 +52,8 @@ static const struct in6_addr in6addr_any =
 #endif 
 
 static listener_t *ListenerPollList = NULL;
+static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data);\r
+static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data);
 
 static listener_t *
 make_listener(struct rb_sockaddr_storage *addr)
@@ -164,6 +166,7 @@ static int
 inetport(listener_t *listener)
 {
        rb_fde_t *F;
+       int ret;
        int opt = 1;
 
        /*
@@ -357,12 +360,12 @@ add_listener(int port, const char *vhost_ip, int family)
        switch(family)
        {
                case AF_INET:
-                       SET_SS_LEN(vaddr, sizeof(struct sockaddr_in));
+                       SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in));
                        ((struct sockaddr_in *)&vaddr)->sin_port = htons(port);
                        break;
 #ifdef IPV6
                case AF_INET6:
-                       SET_SS_LEN(vaddr, sizeof(struct sockaddr_in6));
+                       SET_SS_LEN(&vaddr, sizeof(struct sockaddr_in6));
                        ((struct sockaddr_in6 *)&vaddr)->sin6_port = htons(port);
                        break;
 #endif
@@ -438,8 +441,8 @@ close_listeners()
  * The client is sent to the auth module for verification, and not put in
  * any client list yet.
  */
-static void
-add_connection(listener_t *listener, int fd, struct sockaddr *sai, int exempt)
+static void\r
+add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, int exempt)
 {
        struct Client *new_client;
        s_assert(NULL != listener);
@@ -462,7 +465,7 @@ add_connection(listener_t *listener, int fd, struct sockaddr *sai, int exempt)
 
        strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));
 
-       new_client->localClient->F = rb_add_fd(fd);
+       new_client->localClient->F = F;
 
        new_client->localClient->listener = listener;
        ++listener->ref_count;
@@ -477,3 +480,80 @@ add_connection(listener_t *listener, int fd, struct sockaddr *sai, int exempt)
 
        start_auth(new_client);
 }
+
+static int\r
+accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)\r
+{\r
+       struct Listener *listener = (struct Listener *)data;\r
+       char buf[BUFSIZE];\r
+       struct ConfItem *aconf;\r
+       static time_t last_oper_notice = 0;\r
+\r
+       if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */\r
+       {\r
+               ++ServerStats->is_ref;\r
+               /*\r
+                * slow down the whining to opers bit\r
+                */\r
+               if((last_oper_notice + 20) <= rb_current_time())\r
+               {\r
+                       sendto_realops_flags(SNO_GENERAL, L_ALL,\r
+                                            "All connections in use. (%s)",\r
+                                            get_listener_name(listener));\r
+                       last_oper_notice = rb_current_time();\r
+               }\r
+                       \r
+               rb_write(F, "ERROR :All connections in use\r\n", 32);\r
+               rb_close(F);\r
+               /* Re-register a new IO request for the next accept .. */\r
+               return 0;\r
+       }\r
+\r
+       aconf = find_dline(addr, addr.ss_family);\r
+       if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE))\r
+               return 1;\r
+       \r
+       /* Do an initial check we aren't connecting too fast or with too many\r
+        * from this IP... */\r
+       if(aconf != NULL)\r
+       {\r
+               ServerStats->is_ref++;\r
+                       \r
+               if(ConfigFileEntry.dline_with_reason)\r
+               {\r
+                       if (rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (int)(sizeof(buf)-1))\r
+                       {\r
+                               buf[sizeof(buf) - 3] = '\r';\r
+                               buf[sizeof(buf) - 2] = '\n';\r
+                               buf[sizeof(buf) - 1] = '\0';\r
+                       }\r
+               }\r
+               else\r
+                       strcpy(buf, "ERROR :You have been D-lined.\r\n");\r
+       \r
+               rb_write(F, buf, strlen(buf));\r
+               rb_close(F);\r
+               return 0;\r
+       }\r
+\r
+       return 1;\r
+}\r
+\r
+static void\r
+accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data)\r
+{\r
+       struct Listener *listener = data;\r
+       struct rb_sockaddr_storage lip;\r
+       unsigned int locallen = sizeof(struct rb_sockaddr_storage);\r
+       \r
+       ServerStats->is_ac++;\r
+\r
+       if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0)\r
+       {\r
+               /* this shouldn't fail so... */\r
+               /* XXX add logging of this */\r
+               rb_close(F);\r
+       }\r
+       \r
+       add_connection(listener, F, addr, (struct sockaddr *)&lip, 1);\r
+}