1132943Sgshapiro/* 2261370Sgshapiro * Copyright (c) 2003 Proofpoint, Inc. and its suppliers. 3132943Sgshapiro * All rights reserved. 4132943Sgshapiro * 5132943Sgshapiro * By using this file, you agree to the terms and conditions set 6132943Sgshapiro * forth in the LICENSE file which can be found at the top level of 7132943Sgshapiro * the sendmail distribution. 8132943Sgshapiro * 9132943Sgshapiro * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris 10132943Sgshapiro * Jose-Marcio.Martins@ensmp.fr 11132943Sgshapiro */ 12132943Sgshapiro 13132943Sgshapiro/* a part of this code is based on inetd.c for which this copyright applies: */ 14132943Sgshapiro/* 15132943Sgshapiro * Copyright (c) 1983, 1991, 1993, 1994 16132943Sgshapiro * The Regents of the University of California. All rights reserved. 17132943Sgshapiro * 18132943Sgshapiro * Redistribution and use in source and binary forms, with or without 19132943Sgshapiro * modification, are permitted provided that the following conditions 20132943Sgshapiro * are met: 21132943Sgshapiro * 1. Redistributions of source code must retain the above copyright 22132943Sgshapiro * notice, this list of conditions and the following disclaimer. 23132943Sgshapiro * 2. Redistributions in binary form must reproduce the above copyright 24132943Sgshapiro * notice, this list of conditions and the following disclaimer in the 25132943Sgshapiro * documentation and/or other materials provided with the distribution. 26132943Sgshapiro * 3. All advertising materials mentioning features or use of this software 27132943Sgshapiro * must display the following acknowledgement: 28132943Sgshapiro * This product includes software developed by the University of 29132943Sgshapiro * California, Berkeley and its contributors. 30132943Sgshapiro * 4. Neither the name of the University nor the names of its contributors 31132943Sgshapiro * may be used to endorse or promote products derived from this software 32132943Sgshapiro * without specific prior written permission. 33132943Sgshapiro * 34132943Sgshapiro * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 35132943Sgshapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 36132943Sgshapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 37132943Sgshapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 38132943Sgshapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 39132943Sgshapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 40132943Sgshapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 41132943Sgshapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 42132943Sgshapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 43132943Sgshapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 44132943Sgshapiro * SUCH DAMAGE. 45132943Sgshapiro */ 46132943Sgshapiro 47132943Sgshapiro#include <sendmail.h> 48266711SgshapiroSM_RCSID("@(#)$Id: ratectrl.c,v 8.14 2013-11-22 20:51:56 ca Exp $") 49132943Sgshapiro 50132943Sgshapiro/* 51132943Sgshapiro** stuff included - given some warnings (inet_ntoa) 52132943Sgshapiro** - surely not everything is needed 53132943Sgshapiro*/ 54132943Sgshapiro 55132943Sgshapiro#if NETINET || NETINET6 56132943Sgshapiro# include <arpa/inet.h> 57132943Sgshapiro#endif /* NETINET || NETINET6 */ 58132943Sgshapiro 59157001Sgshapiro#include <sm/time.h> 60132943Sgshapiro 61132943Sgshapiro#ifndef HASH_ALG 62132943Sgshapiro# define HASH_ALG 2 63132943Sgshapiro#endif /* HASH_ALG */ 64132943Sgshapiro 65132943Sgshapiro#ifndef RATECTL_DEBUG 66132943Sgshapiro# define RATECTL_DEBUG 0 67132943Sgshapiro#endif /* RATECTL_DEBUG */ 68132943Sgshapiro 69132943Sgshapiro/* forward declarations */ 70132943Sgshapirostatic int client_rate __P((time_t, SOCKADDR *, bool)); 71132943Sgshapirostatic int total_rate __P((time_t, bool)); 72132943Sgshapiro 73132943Sgshapiro/* 74132943Sgshapiro** CONNECTION_RATE_CHECK - updates connection history data 75132943Sgshapiro** and computes connection rate for the given host 76132943Sgshapiro** 77132943Sgshapiro** Parameters: 78132943Sgshapiro** hostaddr -- ip address of smtp client 79132943Sgshapiro** e -- envelope 80132943Sgshapiro** 81132943Sgshapiro** Returns: 82132943Sgshapiro** true (always) 83132943Sgshapiro** 84132943Sgshapiro** Side Effects: 85132943Sgshapiro** updates connection history 86132943Sgshapiro** 87132943Sgshapiro** Warnings: 88132943Sgshapiro** For each connection, this call shall be 89132943Sgshapiro** done only once with the value true for the 90132943Sgshapiro** update parameter. 91132943Sgshapiro** Typically, this call is done with the value 92132943Sgshapiro** true by the father, and once again with 93132943Sgshapiro** the value false by the children. 94132943Sgshapiro** 95132943Sgshapiro*/ 96132943Sgshapiro 97132943Sgshapirobool 98132943Sgshapiroconnection_rate_check(hostaddr, e) 99132943Sgshapiro SOCKADDR *hostaddr; 100132943Sgshapiro ENVELOPE *e; 101132943Sgshapiro{ 102132943Sgshapiro time_t now; 103132943Sgshapiro int totalrate, clientrate; 104132943Sgshapiro static int clientconn = 0; 105132943Sgshapiro 106132943Sgshapiro now = time(NULL); 107132943Sgshapiro#if RATECTL_DEBUG 108132943Sgshapiro sm_syslog(LOG_INFO, NOQID, "connection_rate_check entering..."); 109132943Sgshapiro#endif /* RATECTL_DEBUG */ 110132943Sgshapiro 111132943Sgshapiro /* update server connection rate */ 112132943Sgshapiro totalrate = total_rate(now, e == NULL); 113132943Sgshapiro#if RATECTL_DEBUG 114182352Sgshapiro sm_syslog(LOG_INFO, NOQID, "global connection rate: %d", totalrate); 115132943Sgshapiro#endif /* RATECTL_DEBUG */ 116132943Sgshapiro 117132943Sgshapiro /* update client connection rate */ 118132943Sgshapiro clientrate = client_rate(now, hostaddr, e == NULL); 119132943Sgshapiro 120132943Sgshapiro if (e == NULL) 121132943Sgshapiro clientconn = count_open_connections(hostaddr); 122132943Sgshapiro 123132943Sgshapiro if (e != NULL) 124132943Sgshapiro { 125132943Sgshapiro char s[16]; 126132943Sgshapiro 127132943Sgshapiro sm_snprintf(s, sizeof(s), "%d", clientrate); 128132943Sgshapiro macdefine(&e->e_macro, A_TEMP, macid("{client_rate}"), s); 129132943Sgshapiro sm_snprintf(s, sizeof(s), "%d", totalrate); 130132943Sgshapiro macdefine(&e->e_macro, A_TEMP, macid("{total_rate}"), s); 131132943Sgshapiro sm_snprintf(s, sizeof(s), "%d", clientconn); 132132943Sgshapiro macdefine(&e->e_macro, A_TEMP, macid("{client_connections}"), 133132943Sgshapiro s); 134132943Sgshapiro } 135132943Sgshapiro return true; 136132943Sgshapiro} 137132943Sgshapiro 138132943Sgshapiro/* 139132943Sgshapiro** Data declarations needed to evaluate connection rate 140132943Sgshapiro*/ 141132943Sgshapiro 142132943Sgshapirostatic int CollTime = 60; 143132943Sgshapiro 144132943Sgshapiro/* this should be a power of 2, otherwise CPMHMASK doesn't work well */ 145132943Sgshapiro#ifndef CPMHSIZE 146132943Sgshapiro# define CPMHSIZE 1024 147132943Sgshapiro#endif /* CPMHSIZE */ 148132943Sgshapiro 149132943Sgshapiro#define CPMHMASK (CPMHSIZE-1) 150132943Sgshapiro 151132943Sgshapiro#ifndef MAX_CT_STEPS 152132943Sgshapiro# define MAX_CT_STEPS 10 153132943Sgshapiro#endif /* MAX_CT_STEPS */ 154132943Sgshapiro 155132943Sgshapiro/* 156132943Sgshapiro** time granularity: 10s (that's one "tick") 157132943Sgshapiro** will be initialised to ConnectionRateWindowSize/CHTSIZE 158132943Sgshapiro** before being used the first time 159132943Sgshapiro*/ 160132943Sgshapiro 161132943Sgshapirostatic int ChtGran = -1; 162132943Sgshapiro 163132943Sgshapiro#define CHTSIZE 6 164132943Sgshapiro 165132943Sgshapiro/* Number of connections for a certain "tick" */ 166132943Sgshapirotypedef struct CTime 167132943Sgshapiro{ 168132943Sgshapiro unsigned long ct_Ticks; 169132943Sgshapiro int ct_Count; 170132943Sgshapiro} 171132943SgshapiroCTime_T; 172132943Sgshapiro 173132943Sgshapirotypedef struct CHash 174132943Sgshapiro{ 175132943Sgshapiro#if NETINET6 && NETINET 176132943Sgshapiro union 177132943Sgshapiro { 178132943Sgshapiro struct in_addr c4_Addr; 179132943Sgshapiro struct in6_addr c6_Addr; 180132943Sgshapiro } cu_Addr; 181132943Sgshapiro# define ch_Addr4 cu_Addr.c4_Addr 182132943Sgshapiro# define ch_Addr6 cu_Addr.c6_Addr 183132943Sgshapiro#else /* NETINET6 && NETINET */ 184132943Sgshapiro# if NETINET6 185132943Sgshapiro struct in6_addr ch_Addr; 186132943Sgshapiro# define ch_Addr6 ch_Addr 187132943Sgshapiro# else /* NETINET6 */ 188132943Sgshapiro struct in_addr ch_Addr; 189132943Sgshapiro# define ch_Addr4 ch_Addr 190132943Sgshapiro# endif /* NETINET6 */ 191132943Sgshapiro#endif /* NETINET6 && NETINET */ 192132943Sgshapiro 193132943Sgshapiro int ch_Family; 194132943Sgshapiro time_t ch_LTime; 195132943Sgshapiro unsigned long ch_colls; 196132943Sgshapiro 197132943Sgshapiro /* 6 buckets for ticks: 60s */ 198132943Sgshapiro CTime_T ch_Times[CHTSIZE]; 199132943Sgshapiro} 200132943SgshapiroCHash_T; 201132943Sgshapiro 202132943Sgshapirostatic CHash_T CHashAry[CPMHSIZE]; 203132943Sgshapirostatic bool CHashAryOK = false; 204132943Sgshapiro 205132943Sgshapiro/* 206132943Sgshapiro** CLIENT_RATE - Evaluate connection rate per smtp client 207132943Sgshapiro** 208132943Sgshapiro** Parameters: 209132943Sgshapiro** now - current time in secs 210132943Sgshapiro** saddr - client address 211132943Sgshapiro** update - update data / check only 212132943Sgshapiro** 213132943Sgshapiro** Returns: 214132943Sgshapiro** connection rate (connections / ConnectionRateWindowSize) 215132943Sgshapiro** 216132943Sgshapiro** Side effects: 217132943Sgshapiro** update static global data 218132943Sgshapiro** 219132943Sgshapiro*/ 220132943Sgshapiro 221132943Sgshapirostatic int 222132943Sgshapiroclient_rate(now, saddr, update) 223132943Sgshapiro time_t now; 224132943Sgshapiro SOCKADDR *saddr; 225132943Sgshapiro bool update; 226132943Sgshapiro{ 227132943Sgshapiro unsigned int hv; 228132943Sgshapiro int i; 229132943Sgshapiro int cnt; 230132943Sgshapiro bool coll; 231132943Sgshapiro CHash_T *chBest = NULL; 232132943Sgshapiro unsigned int ticks; 233132943Sgshapiro 234132943Sgshapiro cnt = 0; 235132943Sgshapiro hv = 0xABC3D20F; 236132943Sgshapiro if (ChtGran < 0) 237132943Sgshapiro ChtGran = ConnectionRateWindowSize / CHTSIZE; 238132943Sgshapiro if (ChtGran <= 0) 239132943Sgshapiro ChtGran = 10; 240132943Sgshapiro 241132943Sgshapiro ticks = now / ChtGran; 242132943Sgshapiro 243132943Sgshapiro if (!CHashAryOK) 244132943Sgshapiro { 245168515Sgshapiro memset(CHashAry, 0, sizeof(CHashAry)); 246132943Sgshapiro CHashAryOK = true; 247132943Sgshapiro } 248132943Sgshapiro 249132943Sgshapiro { 250132943Sgshapiro char *p; 251132943Sgshapiro int addrlen; 252132943Sgshapiro#if HASH_ALG != 1 253132943Sgshapiro int c, d; 254132943Sgshapiro#endif /* HASH_ALG != 1 */ 255132943Sgshapiro 256132943Sgshapiro switch (saddr->sa.sa_family) 257132943Sgshapiro { 258132943Sgshapiro#if NETINET 259132943Sgshapiro case AF_INET: 260132943Sgshapiro p = (char *)&saddr->sin.sin_addr; 261132943Sgshapiro addrlen = sizeof(struct in_addr); 262132943Sgshapiro break; 263132943Sgshapiro#endif /* NETINET */ 264132943Sgshapiro#if NETINET6 265132943Sgshapiro case AF_INET6: 266132943Sgshapiro p = (char *)&saddr->sin6.sin6_addr; 267132943Sgshapiro addrlen = sizeof(struct in6_addr); 268132943Sgshapiro break; 269132943Sgshapiro#endif /* NETINET6 */ 270132943Sgshapiro default: 271132943Sgshapiro /* should not happen */ 272132943Sgshapiro return -1; 273132943Sgshapiro } 274132943Sgshapiro 275132943Sgshapiro /* compute hash value */ 276132943Sgshapiro for (i = 0; i < addrlen; ++i, ++p) 277132943Sgshapiro#if HASH_ALG == 1 278132943Sgshapiro hv = (hv << 5) ^ (hv >> 23) ^ *p; 279132943Sgshapiro hv = (hv ^ (hv >> 16)); 280132943Sgshapiro#elif HASH_ALG == 2 281132943Sgshapiro { 282132943Sgshapiro d = *p; 283132943Sgshapiro c = d; 284132943Sgshapiro c ^= c<<6; 285132943Sgshapiro hv += (c<<11) ^ (c>>1); 286132943Sgshapiro hv ^= (d<<14) + (d<<7) + (d<<4) + d; 287132943Sgshapiro } 288132943Sgshapiro#elif HASH_ALG == 3 289132943Sgshapiro { 290132943Sgshapiro hv = (hv << 4) + *p; 291132943Sgshapiro d = hv & 0xf0000000; 292132943Sgshapiro if (d != 0) 293132943Sgshapiro { 294132943Sgshapiro hv ^= (d >> 24); 295132943Sgshapiro hv ^= d; 296132943Sgshapiro } 297132943Sgshapiro } 298132943Sgshapiro#else /* HASH_ALG == 1 */ 299132943Sgshapiro hv = ((hv << 1) ^ (*p & 0377)) % cctx->cc_size; 300132943Sgshapiro#endif /* HASH_ALG == 1 */ 301132943Sgshapiro } 302132943Sgshapiro 303132943Sgshapiro coll = true; 304132943Sgshapiro for (i = 0; i < MAX_CT_STEPS; ++i) 305132943Sgshapiro { 306132943Sgshapiro CHash_T *ch = &CHashAry[(hv + i) & CPMHMASK]; 307132943Sgshapiro 308132943Sgshapiro#if NETINET 309132943Sgshapiro if (saddr->sa.sa_family == AF_INET && 310132943Sgshapiro ch->ch_Family == AF_INET && 311132943Sgshapiro (saddr->sin.sin_addr.s_addr == ch->ch_Addr4.s_addr || 312132943Sgshapiro ch->ch_Addr4.s_addr == 0)) 313132943Sgshapiro { 314132943Sgshapiro chBest = ch; 315132943Sgshapiro coll = false; 316132943Sgshapiro break; 317132943Sgshapiro } 318132943Sgshapiro#endif /* NETINET */ 319132943Sgshapiro#if NETINET6 320132943Sgshapiro if (saddr->sa.sa_family == AF_INET6 && 321132943Sgshapiro ch->ch_Family == AF_INET6 && 322132943Sgshapiro (IN6_ARE_ADDR_EQUAL(&saddr->sin6.sin6_addr, 323132943Sgshapiro &ch->ch_Addr6) != 0 || 324132943Sgshapiro IN6_IS_ADDR_UNSPECIFIED(&ch->ch_Addr6))) 325132943Sgshapiro { 326132943Sgshapiro chBest = ch; 327132943Sgshapiro coll = false; 328132943Sgshapiro break; 329132943Sgshapiro } 330132943Sgshapiro#endif /* NETINET6 */ 331132943Sgshapiro if (chBest == NULL || ch->ch_LTime == 0 || 332132943Sgshapiro ch->ch_LTime < chBest->ch_LTime) 333132943Sgshapiro chBest = ch; 334132943Sgshapiro } 335132943Sgshapiro 336132943Sgshapiro /* Let's update data... */ 337132943Sgshapiro if (update) 338132943Sgshapiro { 339132943Sgshapiro if (coll && (now - chBest->ch_LTime < CollTime)) 340132943Sgshapiro { 341132943Sgshapiro /* 342132943Sgshapiro ** increment the number of collisions last 343132943Sgshapiro ** CollTime for this client 344132943Sgshapiro */ 345132943Sgshapiro 346132943Sgshapiro chBest->ch_colls++; 347132943Sgshapiro 348132943Sgshapiro /* 349132943Sgshapiro ** Maybe shall log if collision rate is too high... 350132943Sgshapiro ** and take measures to resize tables 351132943Sgshapiro ** if this is the case 352132943Sgshapiro */ 353132943Sgshapiro } 354132943Sgshapiro 355132943Sgshapiro /* 356132943Sgshapiro ** If it's not a match, then replace the data. 357132943Sgshapiro ** Note: this purges the history of a colliding entry, 358132943Sgshapiro ** which may cause "overruns", i.e., if two entries are 359132943Sgshapiro ** "cancelling" each other out, then they may exceed 360132943Sgshapiro ** the limits that are set. This might be mitigated a bit 361132943Sgshapiro ** by the above "best of 5" function however. 362132943Sgshapiro ** 363132943Sgshapiro ** Alternative approach: just use the old data, which may 364132943Sgshapiro ** cause false positives however. 365132943Sgshapiro ** To activate this, change deactivate following memset call. 366132943Sgshapiro */ 367132943Sgshapiro 368132943Sgshapiro if (coll) 369132943Sgshapiro { 370132943Sgshapiro#if NETINET 371132943Sgshapiro if (saddr->sa.sa_family == AF_INET) 372132943Sgshapiro { 373132943Sgshapiro chBest->ch_Family = AF_INET; 374132943Sgshapiro chBest->ch_Addr4 = saddr->sin.sin_addr; 375132943Sgshapiro } 376132943Sgshapiro#endif /* NETINET */ 377132943Sgshapiro#if NETINET6 378132943Sgshapiro if (saddr->sa.sa_family == AF_INET6) 379132943Sgshapiro { 380132943Sgshapiro chBest->ch_Family = AF_INET6; 381132943Sgshapiro chBest->ch_Addr6 = saddr->sin6.sin6_addr; 382132943Sgshapiro } 383132943Sgshapiro#endif /* NETINET6 */ 384132943Sgshapiro#if 1 385132943Sgshapiro memset(chBest->ch_Times, '\0', 386168515Sgshapiro sizeof(chBest->ch_Times)); 387132943Sgshapiro#endif /* 1 */ 388132943Sgshapiro } 389132943Sgshapiro 390132943Sgshapiro chBest->ch_LTime = now; 391132943Sgshapiro { 392132943Sgshapiro CTime_T *ct = &chBest->ch_Times[ticks % CHTSIZE]; 393132943Sgshapiro 394132943Sgshapiro if (ct->ct_Ticks != ticks) 395132943Sgshapiro { 396132943Sgshapiro ct->ct_Ticks = ticks; 397132943Sgshapiro ct->ct_Count = 0; 398132943Sgshapiro } 399132943Sgshapiro ++ct->ct_Count; 400132943Sgshapiro } 401132943Sgshapiro } 402132943Sgshapiro 403132943Sgshapiro /* Now let's count connections on the window */ 404132943Sgshapiro for (i = 0; i < CHTSIZE; ++i) 405132943Sgshapiro { 406132943Sgshapiro CTime_T *ct = &chBest->ch_Times[i]; 407132943Sgshapiro 408132943Sgshapiro if (ct->ct_Ticks <= ticks && ct->ct_Ticks >= ticks - CHTSIZE) 409132943Sgshapiro cnt += ct->ct_Count; 410132943Sgshapiro } 411132943Sgshapiro 412132943Sgshapiro#if RATECTL_DEBUG 413132943Sgshapiro sm_syslog(LOG_WARNING, NOQID, 414132943Sgshapiro "cln: cnt=(%d), CHTSIZE=(%d), ChtGran=(%d)", 415132943Sgshapiro cnt, CHTSIZE, ChtGran); 416132943Sgshapiro#endif /* RATECTL_DEBUG */ 417132943Sgshapiro return cnt; 418132943Sgshapiro} 419132943Sgshapiro 420132943Sgshapiro/* 421132943Sgshapiro** TOTAL_RATE - Evaluate global connection rate 422132943Sgshapiro** 423132943Sgshapiro** Parameters: 424132943Sgshapiro** now - current time in secs 425132943Sgshapiro** update - update data / check only 426132943Sgshapiro** 427132943Sgshapiro** Returns: 428132943Sgshapiro** connection rate (connections / ConnectionRateWindowSize) 429132943Sgshapiro*/ 430132943Sgshapiro 431132943Sgshapirostatic CTime_T srv_Times[CHTSIZE]; 432132943Sgshapirostatic bool srv_Times_OK = false; 433132943Sgshapiro 434132943Sgshapirostatic int 435132943Sgshapirototal_rate(now, update) 436132943Sgshapiro time_t now; 437132943Sgshapiro bool update; 438132943Sgshapiro{ 439132943Sgshapiro int i; 440132943Sgshapiro int cnt = 0; 441132943Sgshapiro CTime_T *ct; 442132943Sgshapiro unsigned int ticks; 443132943Sgshapiro 444132943Sgshapiro if (ChtGran < 0) 445132943Sgshapiro ChtGran = ConnectionRateWindowSize / CHTSIZE; 446132943Sgshapiro if (ChtGran == 0) 447132943Sgshapiro ChtGran = 10; 448132943Sgshapiro ticks = now / ChtGran; 449132943Sgshapiro if (!srv_Times_OK) 450132943Sgshapiro { 451132943Sgshapiro memset(srv_Times, 0, sizeof(srv_Times)); 452132943Sgshapiro srv_Times_OK = true; 453132943Sgshapiro } 454132943Sgshapiro 455132943Sgshapiro /* Let's update data */ 456132943Sgshapiro if (update) 457132943Sgshapiro { 458132943Sgshapiro ct = &srv_Times[ticks % CHTSIZE]; 459132943Sgshapiro 460132943Sgshapiro if (ct->ct_Ticks != ticks) 461132943Sgshapiro { 462132943Sgshapiro ct->ct_Ticks = ticks; 463132943Sgshapiro ct->ct_Count = 0; 464132943Sgshapiro } 465132943Sgshapiro ++ct->ct_Count; 466132943Sgshapiro } 467132943Sgshapiro 468132943Sgshapiro /* Let's count connections on the window */ 469132943Sgshapiro for (i = 0; i < CHTSIZE; ++i) 470132943Sgshapiro { 471132943Sgshapiro ct = &srv_Times[i]; 472132943Sgshapiro 473132943Sgshapiro if (ct->ct_Ticks <= ticks && ct->ct_Ticks >= ticks - CHTSIZE) 474132943Sgshapiro cnt += ct->ct_Count; 475132943Sgshapiro } 476132943Sgshapiro 477132943Sgshapiro#if RATECTL_DEBUG 478132943Sgshapiro sm_syslog(LOG_WARNING, NOQID, 479132943Sgshapiro "srv: cnt=(%d), CHTSIZE=(%d), ChtGran=(%d)", 480132943Sgshapiro cnt, CHTSIZE, ChtGran); 481132943Sgshapiro#endif /* RATECTL_DEBUG */ 482132943Sgshapiro 483132943Sgshapiro return cnt; 484132943Sgshapiro} 485