add unlimited flood priv
[ircu2.10.12-pk.git] / ircd / s_bsd.c
index 6ce42154deed60315319f03f0d949cdfe5be15c0..cc77c7bc87f3dc68a340022234c2b2128bf18fc6 100644 (file)
@@ -132,13 +132,7 @@ void report_error(const char* text, const char* who, int err)
   if (EmptyString(who))
     who = "unknown";
 
-  if (last_notice + 20 < CurrentTime) {
-    /*
-     * pace error messages so opers don't get flooded by transients
-     */
-    sendto_opmask_butone(0, SNO_OLDSNO, text, who, errmsg);
-    last_notice = CurrentTime;
-  }
+  sendto_opmask_butone_ratelimited(0, SNO_OLDSNO, &last_notice, text, who, errmsg);
   log_write(LS_SOCKET, L_ERROR, 0, text, who, errmsg);
   errno = errtmp;
 }
@@ -188,7 +182,7 @@ int init_connection_limits(void)
   if (0 == limit)
     return 1;
   if (limit < 0) {
-    fprintf(stderr, "error setting max fd's to %d\n", limit);
+    fprintf(stderr, "error setting max fds to %d: %s\n", limit, strerror(errno));
   }
   else if (limit > 0) {
     fprintf(stderr, "ircd fd table too big\nHard Limit: %d IRC max: %d\n",
@@ -207,6 +201,8 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
 {
   const struct irc_sockaddr *local;
   IOResult result;
+  int family = 0;
+
   assert(0 != aconf);
   assert(0 != cptr);
   /*
@@ -215,11 +211,12 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
    */
   if (irc_in_addr_valid(&aconf->origin.addr))
     local = &aconf->origin;
-  else if (irc_in_addr_is_ipv4(&aconf->address.addr))
+  else if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
     local = &VirtualHost_v4;
-  else
+    family = AF_INET;
+  } else
     local = &VirtualHost_v6;
-  cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr));
+  cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr), family);
   if (cli_fd(cptr) < 0)
     return 0;
 
@@ -241,7 +238,7 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
   /*
    * Set the TOS bits - this is nonfatal if it doesn't stick.
    */
-  if (!os_set_tos(cli_fd(cptr), FEAT_TOS_SERVER)) {
+  if (!os_set_tos(cli_fd(cptr), feature_int(FEAT_TOS_SERVER))) {
     report_error(TOS_ERROR_MSG, cli_name(cptr), errno);
   }
   if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) {
@@ -355,7 +352,7 @@ static int completed_connection(struct Client* cptr)
    * Make us timeout after twice the timeout for DNS look ups
    */
   cli_lasttime(cptr) = CurrentTime;
-  SetFlag(cptr, FLAG_PINGSENT);
+  ClearPingSent(cptr);
 
   sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
                 cli_name(&me), cli_serv(&me)->timestamp, newts,
@@ -496,7 +493,7 @@ void add_connection(struct Listener* listener, int fd) {
    */
   os_disable_options(fd);
 
-  if (listener->server)
+  if (listener_server(listener))
   {
     new_client = make_client(0, STAT_UNKNOWN_SERVER);
   }
@@ -584,12 +581,11 @@ static int read_packet(struct Client *cptr, int socket_ready)
     case IO_SUCCESS:
       if (length)
       {
-        if (!IsServer(cptr))
-          cli_lasttime(cptr) = CurrentTime;
+        cli_lasttime(cptr) = CurrentTime;
+        ClearPingSent(cptr);
+        ClrFlag(cptr, FLAG_NONL);
         if (cli_lasttime(cptr) > cli_since(cptr))
           cli_since(cptr) = cli_lasttime(cptr);
-        ClrFlag(cptr, FLAG_PINGSENT);
-        ClrFlag(cptr, FLAG_NONL);
       }
       break;
     case IO_BLOCKED:
@@ -619,11 +615,13 @@ static int read_packet(struct Client *cptr, int socket_ready)
     if (length > 0 && dbuf_put(&(cli_recvQ(cptr)), readbuf, length) == 0)
       return exit_client(cptr, cptr, &me, "dbuf_put fail");
 
-    if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD))
+       int HasUnlimitFlood = HasPriv(cptr, PRIV_UNLIMIT_FLOOD);
+  
+    if (DBufLength(&(cli_recvQ(cptr))) > feature_int(FEAT_CLIENT_FLOOD) && !HasUnlimitFlood)
       return exit_client(cptr, cptr, &me, "Excess Flood");
 
     while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && 
-           (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10))
+           (IsTrusted(cptr) || cli_since(cptr) - CurrentTime < 10 || HasUnlimitFlood))
     {
       dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE);
       /*
@@ -639,7 +637,13 @@ static int read_packet(struct Client *cptr, int socket_ready)
         if (DBufLength(&(cli_recvQ(cptr))) < 510)
           SetFlag(cptr, FLAG_NONL);
         else
+        {
+          /* More than 512 bytes in the line - drop the input and yell
+           * at the client.
+           */
           DBufClear(&(cli_recvQ(cptr)));
+          send_reply(cptr, ERR_INPUTTOOLONG);
+        }
       }
       else if (client_dopacket(cptr, dolen) == CPTR_KILLED)
         return CPTR_KILLED;
@@ -860,6 +864,11 @@ static void client_sock_callback(struct Event* ev)
   case ET_ERROR: /* an error occurred */
     fallback = cli_info(cptr);
     cli_error(cptr) = ev_data(ev);
+    /* If the OS told us we have a bad file descriptor, we should
+     * record that for future reference.
+     */
+    if (cli_error(cptr) == EBADF)
+      cli_fd(cptr) = -1;
     if (s_state(&(con_socket(con))) == SS_CONNECTING) {
       completed_connection(cptr);
       /* for some reason, the os_get_sockerr() in completed_connect()