Ticket #15735: patch-tcpserver.c.diff
File patch-tcpserver.c.diff, 8.1 KB (added by compconsultant@…, 16 years ago) |
---|
-
tcpserver.c
diff -ruN tcpserver.c.orig tcpserver.c
old new 1 #ifdef __dietlibc__ 2 #define NO_GETLOADAVG 3 #endif 4 1 5 #include <sys/types.h> 2 6 #include <sys/param.h> 3 7 #include <netdb.h> 8 #include <stdlib.h> 9 #ifdef NO_GETLOADAVG 10 #include <unistd.h> 11 #endif 4 12 #include "uint16.h" 5 13 #include "str.h" 6 14 #include "byte.h" … … 28 36 #include "sig.h" 29 37 #include "dns.h" 30 38 39 40 #ifdef SOLARIS 41 #include <kstat.h> 42 static kstat_ctl_t *kc; 43 #ifndef FSCALE 44 #define FSHIFT 8 /* bits to right of fixed binary point */ 45 #define FSCALE (1<<FSHIFT) 46 #endif /* FSCALE */ 47 48 #define loaddouble(la) ((double)(la) / FSCALE) 49 #endif 50 31 51 int verbosity = 1; 32 52 int flagkillopts = 1; 33 53 int flagdelay = 1; … … 59 79 static stralloc tmp; 60 80 static stralloc fqdn; 61 81 static stralloc addresses; 82 static stralloc diemsg_buf; 83 static stralloc diemsg2_buf; 84 static stralloc diemsg3_buf; 85 static stralloc diemsg4_buf; 62 86 63 87 char bspace[16]; 64 88 buffer b; 65 89 66 90 91 typedef struct 92 { 93 char ip[4]; 94 pid_t pid; 95 } baby; 96 97 baby *child; 67 98 68 99 /* ---------------------------- child */ 69 100 … … 72 103 int flagdeny = 0; 73 104 int flagallownorules = 0; 74 105 char *fnrules = 0; 106 unsigned long maxload = 0; 107 long maxconnip = -1; 108 long maxconnc = -1; 109 char *diemsg = ""; 110 char *diemsg2 = ""; 111 char *diemsg3 = ""; 112 char *diemsg4 = ""; 75 113 76 114 void drop_nomem(void) 77 115 { … … 110 148 strerr_die4sys(111,DROP,"unable to read ",fnrules,": "); 111 149 } 112 150 151 unsigned long limit = 40; 152 113 153 void found(char *data,unsigned int datalen) 114 154 { 115 155 unsigned int next0; … … 125 165 if (data[1 + split] == '=') { 126 166 data[1 + split] = 0; 127 167 env(data + 1,data + 1 + split + 1); 168 if (str_diff(data+1, "MAXLOAD") == 0) scan_ulong(data+1+split+1,&maxload); 169 if (str_diff(data+1, "MAXCONNIP") == 0) scan_ulong(data+1+split+1,&maxconnip); 170 if (str_diff(data+1, "MAXCONNC") == 0) scan_ulong(data+1+split+1,&maxconnc); 171 if (str_diff(data+1, "DIEMSG") == 0) { 172 if (!stralloc_copys(&diemsg_buf,data+1+split+1)) drop_nomem(); 173 if (!stralloc_0(&diemsg_buf)) drop_nomem(); 174 diemsg = diemsg_buf.s; 175 } 176 if (str_diff(data+1, "DIEMSG_MAXLOAD") == 0) { 177 if (!stralloc_copys(&diemsg2_buf,data+1+split+1)) drop_nomem(); 178 if (!stralloc_0(&diemsg2_buf)) drop_nomem(); 179 diemsg2 = diemsg2_buf.s; 180 } 181 if (str_diff(data+1, "DIEMSG_MAXCONNIP") == 0) { 182 if (!stralloc_copys(&diemsg3_buf,data+1+split+1)) drop_nomem(); 183 if (!stralloc_0(&diemsg3_buf)) drop_nomem(); 184 diemsg3 = diemsg3_buf.s; 185 } 186 if (str_diff(data+1, "DIEMSG_MAXCONNC") == 0) { 187 if (!stralloc_copys(&diemsg4_buf,data+1+split+1)) drop_nomem(); 188 if (!stralloc_0(&diemsg4_buf)) drop_nomem(); 189 diemsg4 = diemsg4_buf.s; 190 } 128 191 } 129 192 break; 130 193 } … … 133 196 } 134 197 } 135 198 199 unsigned long getprocla(void) 200 { 201 #ifdef SOLARIS 202 kstat_t *ksp; 203 kstat_named_t *knp; 204 double lavg; 205 kstat_chain_update(kc); 206 ksp = kstat_lookup(kc, "unix", 0, "system_misc"); 207 kstat_read(kc,ksp,NULL); 208 knp = kstat_data_lookup(ksp,"avenrun_1min"); 209 lavg = loaddouble(knp->value.ui32); 210 return (unsigned long)(lavg * 100); 211 #else 212 #ifdef NO_GETLOADAVG 213 int lret; 214 int i; 215 unsigned long u1, u2; 216 char *s; 217 static stralloc loadavg_data = {0}; 218 219 lret = openreadclose("/proc/loadavg", &loadavg_data, 10); 220 if (lret != -1) { 221 /* /proc/loadavg format is: 222 * 13.08 3.04 1.00 34/170 14190 */ 223 s = loadavg_data.s; 224 i = scan_ulong (s, &u1); s+=i; 225 if ((i>0) && (i<5) && (*s == '.')) { /* load should be < 10000 */ 226 i = scan_ulong (s+1,&u2); 227 if (i==2) { /* we require two decimal places */ 228 return (u1 * 100 + u2); 229 } 230 return (u1 * 100); 231 } 232 } 233 #else 234 double result; 235 if (getloadavg(&result, 1) == 1) { 236 return (result * 100); 237 } 238 #endif 239 #endif 240 } 241 136 242 void doit(int t) 137 243 { 138 244 int j; 245 unsigned long curload = 0; 139 246 140 247 remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0; 141 248 … … 211 318 } 212 319 } 213 320 321 if (maxload) { 322 curload = getprocla(); 323 if (curload > maxload) flagdeny = 2; 324 } 325 326 if (!flagdeny && (maxconnip != -1 || maxconnc != -1)) { 327 unsigned long u; 328 long c1=0, cc=0; 329 for (u=0; u < limit; u++) if (child[u].pid != 0) { 330 if ((child[u].ip[0] == remoteip[0]) && 331 (child[u].ip[1] == remoteip[1]) && 332 (child[u].ip[2] == remoteip[2]) ) { 333 cc++; 334 if (child[u].ip[3] == remoteip[3]) c1++; 335 } 336 } 337 if (maxconnc != -1 && (cc >= maxconnc)) flagdeny = 4; 338 if (maxconnip != -1 && (c1 >= maxconnip)) flagdeny = 3; 339 } 340 214 341 if (verbosity >= 2) { 215 342 strnum[fmt_ulong(strnum,getpid())] = 0; 216 343 if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem(); … … 223 350 cats(":"); safecats(remoteipstr); 224 351 cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s); 225 352 cats(":"); safecats(remoteportstr); 353 if (flagdeny == 2) { 354 char curloadstr[FMT_ULONG]; 355 curloadstr[fmt_ulong(curloadstr,curload)] = 0; 356 cats(" "); safecats ("MAXLOAD"); cats(":"); safecats(curloadstr); 357 } 358 if (flagdeny == 3) { 359 char maxconstr[FMT_ULONG]; 360 maxconstr[fmt_ulong(maxconstr,maxconnip)] = 0; 361 cats(" "); safecats ("MAXCONNIP"); cats(":"); safecats(maxconstr); 362 } 363 if (flagdeny == 4) { 364 char maxconstr[FMT_ULONG]; 365 maxconstr[fmt_ulong(maxconstr,maxconnc)] = 0; 366 cats(" "); safecats ("MAXCONNC"); cats(":"); safecats(maxconstr); 367 } 226 368 cats("\n"); 227 369 buffer_putflush(buffer_2,tmp.s,tmp.len); 228 370 } 229 371 230 if (flagdeny) _exit(100); 372 if (flagdeny) { 373 if ((flagdeny==2) && *diemsg2) diemsg = diemsg2; 374 if ((flagdeny==3) && *diemsg3) diemsg = diemsg3; 375 if ((flagdeny==4) && *diemsg4) diemsg = diemsg4; 376 if (*diemsg) { 377 buffer_init(&b,write,t,bspace,sizeof bspace); 378 buffer_puts(&b,diemsg); 379 if (buffer_putsflush(&b,"\r\n") == -1) 380 strerr_die2sys(111,DROP,"unable to print diemsg: "); 381 } 382 sleep(1); 383 _exit(100); 384 } 231 385 } 232 386 233 387 … … 253 407 _exit(100); 254 408 } 255 409 256 unsigned long limit = 40;257 410 unsigned long numchildren = 0; 258 411 259 412 int flag1 = 0; … … 278 431 { 279 432 int wstat; 280 433 int pid; 434 unsigned long u; 281 435 282 436 while ((pid = wait_nohang(&wstat)) > 0) { 283 437 if (verbosity >= 2) { … … 286 440 strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0); 287 441 } 288 442 if (numchildren) --numchildren; printstatus(); 443 for (u=0; u < limit; u++) if (child[u].pid == pid) { child[u].pid = 0; break; } 444 if (u == limit) strerr_die1x(111,"tcpserver: ERROR: dead child not found?!"); /* never happens */ 289 445 } 290 446 } 291 447 … … 299 455 unsigned long u; 300 456 int s; 301 457 int t; 458 pid_t pid; 302 459 303 460 while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof) 304 461 switch(opt) { … … 332 489 argc -= optind; 333 490 argv += optind; 334 491 492 x = env_get("MAXLOAD"); if (x) scan_ulong(x,&maxload); 493 x = env_get("MAXCONNIP"); if (x) scan_ulong(x,&maxconnip); 494 x = env_get("MAXCONNC"); if (x) scan_ulong(x,&maxconnc); 495 x = env_get("DIEMSG"); if (x) diemsg = x; 496 x = env_get("DIEMSG_MAXLOAD"); if (x) diemsg2 = x; 497 x = env_get("DIEMSG_MAXCONNIP"); if (x) diemsg3 = x; 498 x = env_get("DIEMSG_MAXCONNC"); if (x) diemsg4 = x; 499 335 500 if (!verbosity) 336 501 buffer_2->fd = -1; 337 502 … … 352 517 } 353 518 354 519 if (!*argv) usage(); 520 521 child = calloc(sizeof(baby),limit); 522 if (!child) 523 strerr_die2x(111,FATAL,"out of memory for MAXCONNIP tracking"); 355 524 356 525 sig_block(sig_child); 357 526 sig_catch(sig_child,sigchld); … … 393 562 394 563 close(0); 395 564 close(1); 565 #ifdef SOLARIS 566 kc = kstat_open(); 567 #endif 396 568 printstatus(); 397 569 398 570 for (;;) { … … 405 577 if (t == -1) continue; 406 578 ++numchildren; printstatus(); 407 579 408 switch( fork()) {580 switch(pid=fork()) { 409 581 case 0: 410 582 close(s); 411 583 doit(t); … … 420 592 case -1: 421 593 strerr_warn2(DROP,"unable to fork: ",&strerr_sys); 422 594 --numchildren; printstatus(); 595 break; 596 default: 597 for (u=0; u < limit; u++) if (child[u].pid == 0) { byte_copy(child[u].ip,4,remoteip); child[u].pid = pid; break; } 598 if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */ 423 599 } 424 600 close(t); 425 601 }