📄 linetd.c
字号:
}#ifdef USE_IDSA complete = 1; cp[0] = IPPROTO_TCP; cp[1] = ntohs(addr.sin_port); ca = ntohl(addr.sin_addr.s_addr); addrlen = sizeof(struct sockaddr_in); if (getsockname(nfd, (struct sockaddr *) &addr, &addrlen)) { complete = 0; } sp[0] = IPPROTO_TCP; sp[1] = ntohs(addr.sin_port); sa = ntohl(addr.sin_addr.s_addr); ttl = 0; len = sizeof(int); if (getsockopt(nfd, SOL_IP, IP_TTL, (void *) &ttl, &len)) { complete = 0; } if (idsa_set(ic, LINET_CC, LINET_SCHEME, 1, ar, cr, ir, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WSTART, "ip4src", IDSA_T_ADDR, &ca, "portsrc", IDSA_T_PORT, cp, "ip4dst", IDSA_T_ADDR, &sa, "portdst", IDSA_T_PORT, sp, "ipttl", IDSA_T_INT, &ttl, "complete", IDSA_T_FLAG, &complete, "active", IDSA_T_INT, &child_count, NULL) != IDSA_L_ALLOW) { reason=idsa_reason(ic); if(reason){ write(nfd,reason,strlen(reason)); } close(nfd); return -1; }#endif return nfd;}int main(int argc, char **argv){ char *user, *group, *interface, *root, *port, *cmd; int niceinc; int nofork; int timeout; int instances; int queue; int reuse; int keepalive; int what; int value; int offset; int i, j; char c; int lfd; int nfd; struct sigaction sag; sigset_t sst; int status; int hang; int busy; int tos; int ttl; int sane;#ifdef USE_IDSA int exitcode; int killcode; int flags; unsigned int arisk, crisk, irisk, risk;#endif double limit_load = 0.0; port = NULL; user = NULL; group = NULL; root = NULL; interface = NULL; cmd = NULL; sane = 1; reuse = 1; keepalive = 1; niceinc = 0; nofork = 0; timeout = 0; instances = 0; queue = 5; tos = 0; ttl = 0; offset = 0;#ifdef USE_IDSA flags = 0; arisk = idsa_risk_make(-0.3,0.8); crisk = IDSA_R_UNKNOWN; irisk = IDSA_R_PARTIAL;#endif i = j = 1; while (i < argc) { if (argv[i][0] == '-') { c = argv[i][j]; switch (c) { case 'c': printf("(c) 2002 Marc Welz: Licensed under the terms of the GNU General Public License\n"); exit(0); break; case 'h': /* print brief help message */ usage(argv[0]); exit(0); break; case 'v':#ifdef USE_IDSA printf("linetd %s-i\n", VERSION);#else printf("linetd %s\n", VERSION);#endif exit(0); break; /* flags */ case 'f': /* keep in foreground */ nofork = 1; j++; break; case 'a' : /* disable reuse of address */ j++; c = argv[i][j]; switch (c) { case 'r': reuse = 0; break; case 'k': keepalive = 0; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -a requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -a%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break; case 'd' : /* disable sanity checks */ sane = 0; j++; break; /* strings */ case 'u': case 'g': case 'p': case 'r': case 'b': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } switch (c) { case 'u': user = argv[i] + j; break; case 'g': group = argv[i] + j; break; case 'p': port = argv[i] + j; break; case 'r': root = argv[i] + j; break; case 'b': interface = argv[i] + j; break; } i++; j = 1; break; case 'l': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -%c requires a floating point value", c); } load_fd = open(LOADAVG, O_RDONLY); if(load_fd < 0){ fatal_failure(LINET_SYSTEM, errno, "unable to open %s to read load average", LOADAVG); } limit_load = atof(argv[i] + j); i++; j = 1; break; case 'n': case 'm': case 'i': case 'q': case 't': j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -%c requires a numeric value", c); } value = atoi(argv[i] + j); switch (c) { case 'n': niceinc = value; break; case 'm': timeout = value; break; case 'i': instances = value; break; case 'q': queue = value; break; case 't': ttl = value; break; } i++; j = 1; break; case 'o': j++; c = argv[i][j]; switch (c) { case 'c': tos = IPTOS_LOWCOST; break; case 'd': tos = IPTOS_LOWDELAY; break; case 'r': tos = IPTOS_RELIABILITY; break; case 't': tos = IPTOS_THROUGHPUT; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -o requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -o%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break;#ifdef USE_IDSA case 'k' : /* risk ratings */ j++; c = argv[i][j]; j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -k%c requires a parameter", c); } risk = idsa_risk_parse(argv[i]+j); switch (c) { case 'a': arisk = risk; break; case 'c': crisk = risk; break; case 'i': irisk = risk; break; } i++; j = 1; break; case 'x': j++; c = argv[i][j]; switch (c) { case 'e': flags |= IDSA_F_ENV; /* honour IDSA_SOCKET */ break; case 'o': flags |= IDSA_F_FAILOPEN; /* continue on failure */ break; case 'u': flags |= IDSA_F_UPLOAD; /* allow uploading of rules */ break; case '\0': fatal_failure(LINET_USAGE, 0, "option -x requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -x%c", c); break; } j++; if (argv[i][j] == '\0') { j = 1; i++; } break;#endif case 's': j++; c = argv[i][j]; what = 0; switch (c) { case 'c': what = RLIMIT_CORE; break; case 'd': what = RLIMIT_DATA; break; case 'f': what = RLIMIT_FSIZE; break; case 'l': what = RLIMIT_MEMLOCK; break; case 'm': what = RLIMIT_RSS; break; case 'n': what = RLIMIT_NOFILE; break; case 's': what = RLIMIT_STACK; break; case 't': what = RLIMIT_CPU; break; case 'u': what = RLIMIT_NPROC; break; case 'v': what = RLIMIT_AS; break; case '\0': fatal_failure(LINET_USAGE, 0, "option -s requires a modifier"); break; default: fatal_failure(LINET_USAGE, 0, "unknown modifier -s%c", c); break; } j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fatal_failure(LINET_USAGE, 0, "option -s%c requires a parameter", c); } if (!isdigit(argv[i][j])) { fatal_failure(LINET_USAGE, 0, "option -s%c requires a numeric value", c); } value = atoi(argv[i] + j); if(resource_count >= LINET_MAXRES){ fatal_failure(LINET_USAGE, 0, "too many resource restrictions", c); } resource_table[resource_count][0]=what; resource_table[resource_count][1]=value; resource_count++; i++; j = 1; break; case '-': j++; break; case '\0': j = 1; i++; break; default: fatal_failure(LINET_USAGE, 0, "unknown option -%c", argv[i][j]); break; } } else { cmd = argv[i]; offset = i + 1; if (sane) { if (i + 1 >= argc){ fprintf(stderr, "%s: warning: zeroth argument should be specified\n", argv[0]); offset = i; } } i = argc; } } if (cmd == NULL) { fatal_failure(LINET_USAGE, 0, "require a command to run"); } if (!nofork) { fork_parent(argv[0]); }#ifdef USE_IDSA if (ic == NULL) { ic = idsa_open(LINETD, NULL, flags); } if (ic == NULL) { fprintf(stderr, "%s: unable to open idsa connection\n", argv[0]); exit(EX_UNAVAILABLE); }#endif sigfillset(&(sag.sa_mask)); sag.sa_flags = 0; sag.sa_handler = handle_child; if (sigaction(SIGCHLD, &sag, NULL)) { fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler"); } sag.sa_handler = handle_stop; if (sigaction(SIGTERM, &sag, NULL)) { fatal_failure(LINET_SYSTEM, errno, "unable to set signal handler"); } lfd = setup_listener(argv[0], port, interface, queue, ttl, tos, reuse, keepalive); drop_root(argv[0], user, group, root); if(sane){ if(access(cmd, X_OK)){ fatal_failure(LINET_SYSTEM, errno, "\"%s\" %s", cmd, (cmd[0]=='/') ? "appears unavailable" : "might need an absolute path"); } } if (niceinc) { nice(niceinc); }#ifdef USE_IDSA if(idsa_set(ic, LINET_DR, LINET_SCHEME, 1, IDSA_R_SUCCESS, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_SSTART, "version", IDSA_T_STRING, VERSION, NULL) != IDSA_L_ALLOW){ fprintf(stderr, "%s: start disallowed\n", LINETD); return EX_NOPERM; }#endif if (!nofork) { close(STDERR_FILENO); } sigemptyset(&sst); sigaddset(&sst, SIGCHLD); sigaddset(&sst, SIGTERM); sigprocmask(SIG_BLOCK, &sst, NULL); /* disable child signal for everything execpt accept and sleep */ while (run) {#ifdef USE_IDSA nfd = accept_connection(lfd, arisk, crisk, irisk);#else nfd = accept_connection(lfd);#endif if (nfd >= 0) { run_command(lfd, cmd, &argv[offset], nfd, timeout); } do{ /* check children and load */ busy=0; hang = ((instances > 0) && (child_count >= instances)); /* actually wait for child */ if (zombies || hang) { if (waitpid(WAIT_ANY, &status, hang ? 0 : WNOHANG) > 0) { /* collect pids without risk of EINTR */#ifdef USE_IDSA /* in theory this should parse signals and exit codes. Eg SIG{SEGV,BUS} == ES_INTERNAL etc */ if (WIFEXITED(status)) { exitcode = WEXITSTATUS(status); if (exitcode == 0) { idsa_set(ic, LINET_JD, LINET_SCHEME, 0, IDSA_R_NONE, IDSA_R_UNKNOWN, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WSTOP, NULL); } else { idsa_set(ic, LINET_JE, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, IDSA_ES, IDSA_T_STRING, IDSA_ES_OTHER, "exit", IDSA_T_INT, &exitcode, NULL); } } else if (WIFSIGNALED(status)) { killcode = WTERMSIG(status); idsa_set(ic, LINET_JS, LINET_SCHEME, 0, IDSA_R_PARTIAL, IDSA_R_UNKNOWN, IDSA_R_PARTIAL, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_WFAIL, IDSA_ES, IDSA_T_STRING, IDSA_ES_OTHER, "signal", IDSA_T_INT, &killcode, NULL); }#endif child_count--; busy = ! hang; } else { /* nothing more to collect */ zombies = 0; } } if((load_fd >= 0) && (zombies == 0)){ /* if zombies then loop will run again, defer load check */ if(get_load() > limit_load){ /* go to sleep if overloaded */ sigprocmask(SIG_UNBLOCK, &sst, NULL); /* enable child|term signal */ sleep(LINET_SLEEP); sigprocmask(SIG_BLOCK, &sst, NULL); /* disable child|term signal */ busy=run; } } } while (busy); /* end of child and delay loop */ } /* end of main loop */ if(lfd>=0){ close(lfd); } if(load_fd>=0){ close(load_fd); }#ifdef USE_IDSA idsa_set(ic, LINET_DE, LINET_SCHEME, 0, IDSA_R_TOTAL, IDSA_R_NONE, IDSA_R_UNKNOWN, IDSA_SSM, IDSA_T_STRING, IDSA_SSM_SSTOP, "version", IDSA_T_STRING, VERSION, NULL); idsa_close(ic);#endif return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -