int fakeidentd_main(int argc, char **argv) { memset(conns, 0, sizeof(conns)); memset(&G, 0, sizeof(G)); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); /* handle -b <ip> parameter */ bb_getopt_ulflags(argc, argv, "b:", &bind_ip_address); /* handle optional REPLY STRING */ if (optind < argc) G.identuser = argv[optind]; else G.identuser = nobodystr; /* daemonize and have the parent return */ if (godaemon() == 0) return 0; /* main loop where we process all events and never exit */ while (1) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char *buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; if ((l = read(s, buf + len, sizeof(conns[0].buf) - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof(conns[0].buf)) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); if (s < 0) { if (errno != EINTR) /* EINTR */ syslog(LOG_ERR, "accept: %s", strerror(errno)); } else { if (G.conncnt == MAXCONNS) i = closeOldest(); else i = G.conncnt++; movefd(s, i + FCS); /* move if not already there */ FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } /* end of while(1) */ return 0; }
int fakeidentd_main(int argc, char **argv) { int fd; pid_t pid; /* FD_ZERO(&G.readfds); - in bss, already zeroed */ FD_SET(0, &G.readfds); /* handle -b <ip> parameter */ getopt32(argc, argv, "b:", &bind_ip_address); /* handle optional REPLY STRING */ if (optind < argc) G.identuser = argv[optind]; else G.identuser = "******"; writepid(); signal(SIGTERM, handlexitsigs); signal(SIGINT, handlexitsigs); signal(SIGQUIT, handlexitsigs); signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); /* ignore closed connections when writing */ fd = create_and_bind_stream_or_die(bind_ip_address, bb_lookup_port("identd", "tcp", 113)); xlisten(fd, 5); pid = fork(); if (pid < 0) bb_perror_msg_and_die("fork"); if (pid != 0) /* parent */ exit(0); /* child */ setsid(); movefd(fd, 0); while (fd) close(fd--); openlog(applet_name, 0, LOG_DAEMON); logmode = LOGMODE_SYSLOG; /* main loop where we process all events and never exit */ while (1) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char *buf = conns[i].buf; unsigned len = conns[i].len; unsigned l; l = read(s, buf + len, sizeof(conns[0].buf) - len); if (l > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof(conns[0].buf)) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); if (s < 0) { if (errno != EINTR) bb_perror_msg("accept"); } else { if (G.conncnt == MAXCONNS) i = closeOldest(); else i = G.conncnt++; movefd(s, i + FCS); /* move if not already there */ FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } /* end of while (1) */ return 0; }
int main(int argc, char * argv[]) { uid_t nobody, nogrp; memset(conns, 0, sizeof conns); memset(&G, 0, sizeof G); FD_ZERO(&G.readfds); FD_SET(0, &G.readfds); if (argv[1]) { if (argv[1][0] == '-') { if (argv[1][1] == 'V') { printversion('.'); return 0; } else { fdprintf(2, "%s: invalid option -- %c\n", argv[0], argv[1][1]); fdprintf(2, "Usage: %s [-V] " IU_IN_USAGESTR "\n", argv[0]); return 1; } } else { SET_IU(argv[1], argc - 1); } } else { SET_IU(nobodystr, 1); } #ifndef DEBUG close(1); /* not debugging, openlog() hopefully uses fd 1. */ #else close(3); /* debugging, TRACE uses fd 1, openlog() hopefully fd 3 */ #endif openlog("identd", LOG_CONS, LOG_DAEMON); { struct passwd * pw = getpwnam(nobodystr); if (pw) { nobody = pw->pw_uid; nogrp = pw->pw_gid; } else { syslog(LOG_CRIT, "Cannot find user `nobody': %s", strerrno()); return -1; } } if (inetbind(getport()) < 0) { return -1; } /* */ { int i; for (i = FCS; i < MAXCONNS + FCS; i++) { close(i); } } #ifdef DEBUG #ifndef LOG_PERROR #define LOG_PERROR 0 #endif openlog("identd", LOG_PERROR, LOG_DAEMON); #else /* not DEBUG */ godaemon(); openlog("identd", 0, LOG_DAEMON); close(2); signal(SIGHUP, SIG_IGN); #endif /* DEBUG */ signal(SIGPIPE, SIG_IGN); /* connection closed when writing (raises ???) */ writepid(nobody, nogrp); setegid(nogrp); setgid(nogrp); setuid(nobody); seteuid(nobody); { int i; for (i = 0; i < 4; i++) { char * id = (char)NULL; unsigned int rv = 0; switch (i) { case 0: rv = (unsigned int)getegid(); id = "egid"; break; case 1: rv = (unsigned int)getgid(); id = "gid"; break; case 2: rv = (unsigned int)geteuid(); id = "euid"; break; case 3: rv = (unsigned int)getuid(); id = "uid"; break; } if (rv == 0) { syslog(LOG_ERR, "Can not drop all root privileges (%s) !!! %s !!!", id, strerrno()); delpidfile(); return -1; } } } while (2) { fd_set rfds = G.readfds; struct timeval tv = { 15, 0 }; int i; int tim = time(NULL); TRACE(("calling select(): n = %d, rfds = 0x%x\n\n", G.conncnt + FCS, *(int *)&rfds)); select(G.conncnt + FCS, &rfds, NULL, NULL, G.conncnt? &tv: NULL); for (i = G.conncnt - 1; i >= 0; i--) { int s = i + FCS; if (FD_ISSET(s, &rfds)) { char * buf = conns[i].buf; unsigned int len = conns[i].len; unsigned int l; TRACE(("data socket fd_isset %d\n", s)); if ((int)(l = read(s, buf + len, sizeof conns[0].buf - len)) > 0) { if (checkInput(buf, len, l)) { reply(s, buf); goto deleteconn; } else if (len + l >= sizeof conns[0].buf) { replyError(s, "X-INVALID-REQUEST"); goto deleteconn; } else { conns[i].len += l; } } else { goto deleteconn; } conns[i].lasttime = tim; continue; deleteconn: deleteConn(s); } else { /* implement as time_after() in linux kernel sources ... */ if (conns[i].lasttime + MAXIDLETIME <= tim) { replyError(s, "X-TIMEOUT"); deleteConn(s); } } } if (FD_ISSET(0, &rfds)) { int s = accept(0, NULL, 0); TRACE(("server socket fd_isset, %d accepted\n", s)); if (s < 0) { if (errno != EINTR) /* EINTR */ { syslog(LOG_ERR, "accept: %s", strerrno()); } } else { if (G.conncnt == MAXCONNS) { i = closeOldest(); } else { i = G.conncnt++; } if (s != i + FCS) { movesocket(s, i + FCS); } FD_SET(i + FCS, &G.readfds); conns[i].len = 0; conns[i].lasttime = time(NULL); } } } }