From 4f4f7569f6e2e4db54f175e210d369339adb1510 Mon Sep 17 00:00:00 2001 From: sheldonh Date: Thu, 22 Jul 1999 14:11:26 +0000 Subject: Move code for all builtin services from inetd.c to builtins.c, including the Green Piece. :-) In future, new builtin services are less likely to need to touch the already tangled inetd.c . --- usr.sbin/inetd/Makefile | 3 +- usr.sbin/inetd/builtins.c | 505 +++++++++++++++++++++++++++++++++++++++ usr.sbin/inetd/inetd.c | 589 +--------------------------------------------- usr.sbin/inetd/inetd.h | 134 +++++++++++ 4 files changed, 648 insertions(+), 583 deletions(-) create mode 100644 usr.sbin/inetd/builtins.c create mode 100644 usr.sbin/inetd/inetd.h (limited to 'usr.sbin/inetd') diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile index 91c09cc..fb72be4 100644 --- a/usr.sbin/inetd/Makefile +++ b/usr.sbin/inetd/Makefile @@ -1,7 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 6/6/93 -# $Id: Makefile,v 1.10 1999/06/27 18:05:33 sheldonh Exp $ +# $Id: Makefile,v 1.12 1999/07/15 17:01:42 green Exp $ PROG= inetd +SRCS= inetd.c builtins.c MAN8= inetd.8 MLINKS= inetd.8 inetd.conf.5 diff --git a/usr.sbin/inetd/builtins.c b/usr.sbin/inetd/builtins.c new file mode 100644 index 0000000..c4e8973 --- /dev/null +++ b/usr.sbin/inetd/builtins.c @@ -0,0 +1,505 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "inetd.h" + +extern int debug; +extern struct servtab *servtab; + +char ring[128]; +char *endring; + +int check_loop __P((struct sockaddr_in *, struct servtab *sep)); +void inetd_setproctitle __P((char *, int)); + +struct biltin biltins[] = { + /* Echo received data */ + { "echo", SOCK_STREAM, 1, -1, echo_stream }, + { "echo", SOCK_DGRAM, 0, 1, echo_dg }, + + /* Internet /dev/null */ + { "discard", SOCK_STREAM, 1, -1, discard_stream }, + { "discard", SOCK_DGRAM, 0, 1, discard_dg }, + + /* Return 32 bit time since 1970 */ + { "time", SOCK_STREAM, 0, -1, machtime_stream }, + { "time", SOCK_DGRAM, 0, 1, machtime_dg }, + + /* Return human-readable time */ + { "daytime", SOCK_STREAM, 0, -1, daytime_stream }, + { "daytime", SOCK_DGRAM, 0, 1, daytime_dg }, + + /* Familiar character generator */ + { "chargen", SOCK_STREAM, 1, -1, chargen_stream }, + { "chargen", SOCK_DGRAM, 0, 1, chargen_dg }, + + { "tcpmux", SOCK_STREAM, 1, -1, (void (*)())tcpmux }, + + { "auth", SOCK_STREAM, 1, -1, ident_stream }, + + { NULL } +}; + +void +initring() +{ + int i; + + endring = ring; + + for (i = 0; i <= 128; ++i) + if (isprint(i)) + *endring++ = i; +} + +/* ARGSUSED */ +void +chargen_dg(s, sep) /* Character generator */ + int s; + struct servtab *sep; +{ + struct sockaddr_in sin; + static char *rs; + int len, size; + char text[LINESIZ+2]; + + if (endring == 0) { + initring(); + rs = ring; + } + + size = sizeof(sin); + if (recvfrom(s, text, sizeof(text), 0, + (struct sockaddr *)&sin, &size) < 0) + return; + + if (check_loop(&sin, sep)) + return; + + if ((len = endring - rs) >= LINESIZ) + memmove(text, rs, LINESIZ); + else { + memmove(text, rs, len); + memmove(text + len, ring, LINESIZ - len); + } + if (++rs == endring) + rs = ring; + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + (void) sendto(s, text, sizeof(text), 0, + (struct sockaddr *)&sin, sizeof(sin)); +} + +/* ARGSUSED */ +void +chargen_stream(s, sep) /* Character generator */ + int s; + struct servtab *sep; +{ + int len; + char *rs, text[LINESIZ+2]; + + inetd_setproctitle(sep->se_service, s); + + if (!endring) { + initring(); + rs = ring; + } + + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + for (rs = ring;;) { + if ((len = endring - rs) >= LINESIZ) + memmove(text, rs, LINESIZ); + else { + memmove(text, rs, len); + memmove(text + len, ring, LINESIZ - len); + } + if (++rs == endring) + rs = ring; + if (write(s, text, sizeof(text)) != sizeof(text)) + break; + } + exit(0); +} + +/* ARGSUSED */ +void +daytime_dg(s, sep) /* Return human-readable time of day */ + int s; + struct servtab *sep; +{ + char buffer[256]; + time_t clock; + struct sockaddr_in sin; + int size; + + clock = time((time_t *) 0); + + size = sizeof(sin); + if (recvfrom(s, buffer, sizeof(buffer), 0, + (struct sockaddr *)&sin, &size) < 0) + return; + + if (check_loop(&sin, sep)) + return; + + (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); + (void) sendto(s, buffer, strlen(buffer), 0, + (struct sockaddr *)&sin, sizeof(sin)); +} + +/* ARGSUSED */ +void +daytime_stream(s, sep) /* Return human-readable time of day */ + int s; + struct servtab *sep; +{ + char buffer[256]; + time_t clock; + + clock = time((time_t *) 0); + + (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); + (void) write(s, buffer, strlen(buffer)); +} + +/* ARGSUSED */ +void +discard_dg(s, sep) /* Discard service -- ignore data */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + + (void) read(s, buffer, sizeof(buffer)); +} + +/* ARGSUSED */ +void +discard_stream(s, sep) /* Discard service -- ignore data */ + int s; + struct servtab *sep; +{ + int ret; + char buffer[BUFSIZE]; + + inetd_setproctitle(sep->se_service, s); + while (1) { + while ((ret = read(s, buffer, sizeof(buffer))) > 0) + ; + if (ret == 0 || errno != EINTR) + break; + } + exit(0); +} + +/* ARGSUSED */ +void +echo_dg(s, sep) /* Echo service -- echo data back */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + int i, size; + struct sockaddr_in sin; + + size = sizeof(sin); + if ((i = recvfrom(s, buffer, sizeof(buffer), 0, + (struct sockaddr *)&sin, &size)) < 0) + return; + + if (check_loop(&sin, sep)) + return; + + (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin, + sizeof(sin)); +} + +/* ARGSUSED */ +void +echo_stream(s, sep) /* Echo service -- echo data back */ + int s; + struct servtab *sep; +{ + char buffer[BUFSIZE]; + int i; + + inetd_setproctitle(sep->se_service, s); + while ((i = read(s, buffer, sizeof(buffer))) > 0 && + write(s, buffer, i) > 0) + ; + exit(0); +} + +/* ARGSUSED */ +void +iderror(lport, fport, fp, er) + int lport, fport, er; + FILE *fp; +{ + fprintf(fp, "%d , %d : ERROR : %s\r\n", lport, fport, + er == -1 ? "HIDDEN-USER" : er ? strerror(er) : "UNKNOWN-ERROR"); + fflush(fp); + fclose(fp); + + exit(0); +} + +/* ARGSUSED */ +void +ident_stream(s, sep) /* Ident service */ + int s; + struct servtab *sep; +{ + struct sockaddr_in sin[2]; + struct ucred uc; + struct passwd *pw; + FILE *fp; + char buf[BUFSIZE], *cp, **av; + int len, c, rflag = 0, fflag = 0, argc = 0; + u_short lport, fport; + + inetd_setproctitle(sep->se_service, s); + optind = 1; + optreset = 1; + for (av = sep->se_argv; *av; av++) + argc++; + if (argc) { + while ((c = getopt(argc, sep->se_argv, "fr")) != -1) + switch (c) { + case 'f': + fflag = 1; + break; + case 'r': + rflag = 1; + break; + default: + break; + } + } + fp = fdopen(s, "r+"); + len = sizeof(sin[0]); + if (getsockname(s, (struct sockaddr *)&sin[0], &len) == -1) + iderror(0, 0, fp, errno); + len = sizeof(sin[1]); + if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1) + iderror(0, 0, fp, errno); + errno = 0; + if (fgets(buf, sizeof(buf), fp) == NULL) + iderror(0, 0, fp, errno); + buf[BUFSIZE - 1] = '\0'; + strtok(buf, "\r\n"); + cp = strtok(buf, ","); + if (cp == NULL || sscanf(cp, "%hu", &lport) != 1) + iderror(0, 0, fp, 0); + cp = strtok(NULL, ","); + if (cp == NULL || sscanf(cp, "%hu", &fport) != 1) + iderror(0, 0, fp, 0); + if (!rflag) + iderror(lport, fport, fp, -1); + sin[0].sin_port = htons(lport); + sin[1].sin_port = htons(fport); + len = sizeof(uc); + if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin, + sizeof(sin)) == -1) + iderror(lport, fport, fp, errno); + pw = getpwuid(uc.cr_uid); + if (pw == NULL) + iderror(lport, fport, fp, errno); + if (fflag) { + FILE *fakeid = NULL; + char fakeid_path[PATH_MAX]; + struct stat sb; + seteuid(pw->pw_uid); + setegid(pw->pw_gid); + snprintf(fakeid_path, sizeof(fakeid_path), "%s/.fakeid", + pw->pw_dir); + if ((fakeid = fopen(fakeid_path, "r")) != NULL && + fstat(fileno(fakeid), &sb) != -1 && S_ISREG(sb.st_mode)) { + buf[sizeof(buf) - 1] = '\0'; + if (fgets(buf, sizeof(buf), fakeid) == NULL) { + cp = pw->pw_name; + fclose(fakeid); + goto printit; + } + fclose(fakeid); + strtok(buf, "\r\n"); + if (strlen(buf) > 16) + buf[16] = '\0'; + cp = buf; + while (isspace(*cp)) + cp++; + strtok(cp, " \t"); + if (!*cp || getpwnam(cp)) + cp = getpwuid(uc.cr_uid)->pw_name; + } else + cp = pw->pw_name; + } else + cp = pw->pw_name; +printit: + fprintf(fp, "%d , %d : USERID : FreeBSD :%s\r\n", lport, fport, + cp); + fflush(fp); + fclose(fp); + + exit(0); +} + +/* + * Return a machine readable date and time, in the form of the + * number of seconds since midnight, Jan 1, 1900. Since gettimeofday + * returns the number of seconds since midnight, Jan 1, 1970, + * we must add 2208988800 seconds to this figure to make up for + * some seventy years Bell Labs was asleep. + */ + +unsigned long +machtime() +{ + struct timeval tv; + + if (gettimeofday(&tv, (struct timezone *)NULL) < 0) { + if (debug) + warnx("unable to get time of day"); + return (0L); + } +#define OFFSET ((u_long)25567 * 24*60*60) + return (htonl((long)(tv.tv_sec + OFFSET))); +#undef OFFSET +} + +/* ARGSUSED */ +void +machtime_dg(s, sep) + int s; + struct servtab *sep; +{ + unsigned long result; + struct sockaddr_in sin; + int size; + + size = sizeof(sin); + if (recvfrom(s, (char *)&result, sizeof(result), 0, + (struct sockaddr *)&sin, &size) < 0) + return; + + if (check_loop(&sin, sep)) + return; + + result = machtime(); + (void) sendto(s, (char *) &result, sizeof(result), 0, + (struct sockaddr *)&sin, sizeof(sin)); +} + +/* ARGSUSED */ +void +machtime_stream(s, sep) + int s; + struct servtab *sep; +{ + unsigned long result; + + result = machtime(); + (void) write(s, (char *) &result, sizeof(result)); +} + +/* + * Based on TCPMUX.C by Mark K. Lottor November 1988 + * sri-nic::ps:tcpmux.c + */ + +#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ +#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) + +static int /* # of characters upto \r,\n or \0 */ +getline(fd, buf, len) + int fd; + char *buf; + int len; +{ + int count = 0, n; + struct sigaction sa; + + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sa.sa_handler = SIG_DFL; + sigaction(SIGALRM, &sa, (struct sigaction *)0); + do { + alarm(10); + n = read(fd, buf, len-count); + alarm(0); + if (n == 0) + return (count); + if (n < 0) + return (-1); + while (--n >= 0) { + if (*buf == '\r' || *buf == '\n' || *buf == '\0') + return (count); + count++; + buf++; + } + } while (count < len); + return (count); +} + +struct servtab * +tcpmux(s) + int s; +{ + struct servtab *sep; + char service[MAX_SERV_LEN+1]; + int len; + + /* Get requested service name */ + if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { + strwrite(s, "-Error reading service name\r\n"); + return (NULL); + } + service[len] = '\0'; + + if (debug) + warnx("tcpmux: someone wants %s", service); + + /* + * Help is a required command, and lists available services, + * one per line. + */ + if (!strcasecmp(service, "help")) { + for (sep = servtab; sep; sep = sep->se_next) { + if (!ISMUX(sep)) + continue; + (void)write(s,sep->se_service,strlen(sep->se_service)); + strwrite(s, "\r\n"); + } + return (NULL); + } + + /* Try matching a service in inetd.conf with the request */ + for (sep = servtab; sep; sep = sep->se_next) { + if (!ISMUX(sep)) + continue; + if (!strcasecmp(service, sep->se_service)) { + if (ISMUXPLUS(sep)) { + strwrite(s, "+Go\r\n"); + } + return (sep); + } + } + strwrite(s, "-Service not available\r\n"); + return (NULL); +} + diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c index 341c89b..60303da 100644 --- a/usr.sbin/inetd/inetd.c +++ b/usr.sbin/inetd/inetd.c @@ -42,7 +42,7 @@ static const char copyright[] = static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94"; #endif static const char rcsid[] = - "$Id: inetd.c,v 1.62 1999/07/21 12:19:24 sheldonh Exp $"; + "$Id: inetd.c,v 1.63 1999/07/21 16:09:45 sheldonh Exp $"; #endif /* not lint */ /* @@ -104,14 +104,10 @@ static const char rcsid[] = * Comment lines are indicated by a `#' in column 1. */ #include -#include #include -#include #include #include #include -#include -#include #include #include @@ -119,7 +115,6 @@ static const char rcsid[] = #include #include -#include #include #include #include @@ -136,6 +131,9 @@ static const char rcsid[] = #include #include +#include "inetd.h" +#include "pathnames.h" + #ifndef LIBWRAP_ALLOW_FACILITY # define LIBWRAP_ALLOW_FACILITY LOG_AUTH #endif @@ -162,8 +160,6 @@ static const char rcsid[] = #endif -#include "pathnames.h" - #ifndef MAXCHILD #define MAXCHILD -1 /* maximum number of this service < 0 = no limit */ @@ -200,122 +196,9 @@ struct rpcent *rpc; struct in_addr bind_address; int signalpipe[2]; -struct servtab { - char *se_service; /* name of service */ - int se_socktype; /* type of socket to use */ - char *se_proto; /* protocol used */ - int se_maxchild; /* max number of children */ - int se_maxcpm; /* max connects per IP per minute */ - int se_numchild; /* current number of children */ - pid_t *se_pids; /* array of child pids */ - char *se_user; /* user name to run as */ - char *se_group; /* group name to run as */ -#ifdef LOGIN_CAP - char *se_class; /* login class name to run with */ -#endif - struct biltin *se_bi; /* if built-in, description */ - char *se_server; /* server program */ - char *se_server_name; /* server program without path */ -#define MAXARGV 20 - char *se_argv[MAXARGV+1]; /* program arguments */ - int se_fd; /* open descriptor */ - struct sockaddr_in se_ctrladdr;/* bound address */ - u_char se_type; /* type: normal, mux, or mux+ */ - u_char se_checked; /* looked at during merge */ - u_char se_accept; /* i.e., wait/nowait mode */ - u_char se_rpc; /* ==1 if RPC service */ - int se_rpc_prog; /* RPC program number */ - u_int se_rpc_lowvers; /* RPC low version */ - u_int se_rpc_highvers; /* RPC high version */ - int se_count; /* number started since se_time */ - struct timeval se_time; /* start of se_count */ - struct servtab *se_next; -} *servtab; - -#define NORM_TYPE 0 -#define MUX_TYPE 1 -#define MUXPLUS_TYPE 2 -#define TTCP_TYPE 3 -#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ - ((sep)->se_type == MUXPLUS_TYPE)) -#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) -#define ISTTCP(sep) ((sep)->se_type == TTCP_TYPE) - - -void chargen_dg __P((int, struct servtab *)); -void chargen_stream __P((int, struct servtab *)); -void close_sep __P((struct servtab *)); -void flag_signal __P((char)); -void flag_config __P((int)); -void config __P((void)); -void daytime_dg __P((int, struct servtab *)); -void daytime_stream __P((int, struct servtab *)); -void discard_dg __P((int, struct servtab *)); -void discard_stream __P((int, struct servtab *)); -void echo_dg __P((int, struct servtab *)); -void echo_stream __P((int, struct servtab *)); -void endconfig __P((void)); -struct servtab *enter __P((struct servtab *)); -void freeconfig __P((struct servtab *)); -struct servtab *getconfigent __P((void)); -void iderror __P((int, int, FILE *, int)); -void ident_stream __P((int, struct servtab *)); -void machtime_dg __P((int, struct servtab *)); -void machtime_stream __P((int, struct servtab *)); -int matchservent __P((char *, char *, char *)); -char *newstr __P((char *)); -char *nextline __P((FILE *)); -void print_service __P((char *, struct servtab *)); -void addchild __P((struct servtab *, int)); -void flag_reapchild __P((int)); -void reapchild __P((void)); -void enable __P((struct servtab *)); -void disable __P((struct servtab *)); -void flag_retry __P((int)); -void retry __P((void)); -int setconfig __P((void)); -void setup __P((struct servtab *)); -char *sskip __P((char **)); -char *skip __P((char **)); -struct servtab *tcpmux __P((int)); -int cpmip __P((struct servtab *, int)); -void inetd_setproctitle __P((char *, int)); - -void unregisterrpc __P((register struct servtab *sep)); - -struct biltin { - char *bi_service; /* internally provided service name */ - int bi_socktype; /* type of socket supported */ - short bi_fork; /* 1 if should fork before call */ - int bi_maxchild; /* max number of children (-1=default) */ - void (*bi_fn)(); /* function which performs it */ -} biltins[] = { - /* Echo received data */ - { "echo", SOCK_STREAM, 1, -1, echo_stream }, - { "echo", SOCK_DGRAM, 0, 1, echo_dg }, - - /* Internet /dev/null */ - { "discard", SOCK_STREAM, 1, -1, discard_stream }, - { "discard", SOCK_DGRAM, 0, 1, discard_dg }, - - /* Return 32 bit time since 1970 */ - { "time", SOCK_STREAM, 0, -1, machtime_stream }, - { "time", SOCK_DGRAM, 0, 1, machtime_dg }, - - /* Return human-readable time */ - { "daytime", SOCK_STREAM, 0, -1, daytime_stream }, - { "daytime", SOCK_DGRAM, 0, 1, daytime_dg }, - - /* Familiar character generator */ - { "chargen", SOCK_STREAM, 1, -1, chargen_stream }, - { "chargen", SOCK_DGRAM, 0, 1, chargen_dg }, - - { "tcpmux", SOCK_STREAM, 1, -1, (void (*)())tcpmux }, - - { "auth", SOCK_STREAM, 1, -1, ident_stream }, - - { NULL } -}; +struct servtab *servtab; + +extern struct biltin biltins[]; #define NUMINT (sizeof(intab) / sizeof(struct inent)) char *CONFIG = _PATH_INETDCONF; @@ -1626,137 +1509,6 @@ inetd_setproctitle(a, s) /* * Internet services provided internally by inetd: */ -#define BUFSIZE 8192 - -/* ARGSUSED */ -void -iderror(lport, fport, fp, er) - int lport, fport, er; - FILE *fp; -{ - fprintf(fp, "%d , %d : ERROR : %s\r\n", lport, fport, - er == -1 ? "HIDDEN-USER" : er ? strerror(er) : "UNKNOWN-ERROR"); - fflush(fp); - fclose(fp); - - exit(0); -} - -/* ARGSUSED */ -void -ident_stream(s, sep) /* Ident service */ - int s; - struct servtab *sep; -{ - struct sockaddr_in sin[2]; - struct ucred uc; - struct passwd *pw; - FILE *fp; - char buf[BUFSIZE], *cp, **av; - int len, c, rflag = 0, fflag = 0, argc = 0; - u_short lport, fport; - - inetd_setproctitle(sep->se_service, s); - optind = 1; - optreset = 1; - for (av = sep->se_argv; *av; av++) - argc++; - if (argc) { - while ((c = getopt(argc, sep->se_argv, "fr")) != -1) - switch (c) { - case 'f': - fflag = 1; - break; - case 'r': - rflag = 1; - break; - default: - break; - } - } - fp = fdopen(s, "r+"); - len = sizeof(sin[0]); - if (getsockname(s, (struct sockaddr *)&sin[0], &len) == -1) - iderror(0, 0, fp, errno); - len = sizeof(sin[1]); - if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1) - iderror(0, 0, fp, errno); - errno = 0; - if (fgets(buf, sizeof(buf), fp) == NULL) - iderror(0, 0, fp, errno); - buf[BUFSIZE - 1] = '\0'; - strtok(buf, "\r\n"); - cp = strtok(buf, ","); - if (cp == NULL || sscanf(cp, "%hu", &lport) != 1) - iderror(0, 0, fp, 0); - cp = strtok(NULL, ","); - if (cp == NULL || sscanf(cp, "%hu", &fport) != 1) - iderror(0, 0, fp, 0); - if (!rflag) - iderror(lport, fport, fp, -1); - sin[0].sin_port = htons(lport); - sin[1].sin_port = htons(fport); - len = sizeof(uc); - if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin, - sizeof(sin)) == -1) - iderror(lport, fport, fp, errno); - pw = getpwuid(uc.cr_uid); - if (pw == NULL) - iderror(lport, fport, fp, errno); - if (fflag) { - FILE *fakeid = NULL; - char fakeid_path[PATH_MAX]; - struct stat sb; - seteuid(pw->pw_uid); - setegid(pw->pw_gid); - snprintf(fakeid_path, sizeof(fakeid_path), "%s/.fakeid", - pw->pw_dir); - if ((fakeid = fopen(fakeid_path, "r")) != NULL && - fstat(fileno(fakeid), &sb) != -1 && S_ISREG(sb.st_mode)) { - buf[sizeof(buf) - 1] = '\0'; - if (fgets(buf, sizeof(buf), fakeid) == NULL) { - cp = pw->pw_name; - fclose(fakeid); - goto printit; - } - fclose(fakeid); - strtok(buf, "\r\n"); - if (strlen(buf) > 16) - buf[16] = '\0'; - cp = buf; - while (isspace(*cp)) - cp++; - strtok(cp, " \t"); - if (!*cp || getpwnam(cp)) - cp = getpwuid(uc.cr_uid)->pw_name; - } else - cp = pw->pw_name; - } else - cp = pw->pw_name; -printit: - fprintf(fp, "%d , %d : USERID : FreeBSD :%s\r\n", lport, fport, - cp); - fflush(fp); - fclose(fp); - - exit(0); -} - -/* ARGSUSED */ -void -echo_stream(s, sep) /* Echo service -- echo data back */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - int i; - - inetd_setproctitle(sep->se_service, s); - while ((i = read(s, buffer, sizeof(buffer))) > 0 && - write(s, buffer, i) > 0) - ; - exit(0); -} int check_loop(sin, sep) struct sockaddr_in *sin; @@ -1780,245 +1532,6 @@ int check_loop(sin, sep) return 0; } -/* ARGSUSED */ -void -echo_dg(s, sep) /* Echo service -- echo data back */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - int i, size; - struct sockaddr_in sin; - - size = sizeof(sin); - if ((i = recvfrom(s, buffer, sizeof(buffer), 0, - (struct sockaddr *)&sin, &size)) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin, - sizeof(sin)); -} - -/* ARGSUSED */ -void -discard_stream(s, sep) /* Discard service -- ignore data */ - int s; - struct servtab *sep; -{ - int ret; - char buffer[BUFSIZE]; - - inetd_setproctitle(sep->se_service, s); - while (1) { - while ((ret = read(s, buffer, sizeof(buffer))) > 0) - ; - if (ret == 0 || errno != EINTR) - break; - } - exit(0); -} - -/* ARGSUSED */ -void -discard_dg(s, sep) /* Discard service -- ignore data */ - int s; - struct servtab *sep; -{ - char buffer[BUFSIZE]; - - (void) read(s, buffer, sizeof(buffer)); -} - -#include -#define LINESIZ 72 -char ring[128]; -char *endring; - -void -initring() -{ - int i; - - endring = ring; - - for (i = 0; i <= 128; ++i) - if (isprint(i)) - *endring++ = i; -} - -/* ARGSUSED */ -void -chargen_stream(s, sep) /* Character generator */ - int s; - struct servtab *sep; -{ - int len; - char *rs, text[LINESIZ+2]; - - inetd_setproctitle(sep->se_service, s); - - if (!endring) { - initring(); - rs = ring; - } - - text[LINESIZ] = '\r'; - text[LINESIZ + 1] = '\n'; - for (rs = ring;;) { - if ((len = endring - rs) >= LINESIZ) - memmove(text, rs, LINESIZ); - else { - memmove(text, rs, len); - memmove(text + len, ring, LINESIZ - len); - } - if (++rs == endring) - rs = ring; - if (write(s, text, sizeof(text)) != sizeof(text)) - break; - } - exit(0); -} - -/* ARGSUSED */ -void -chargen_dg(s, sep) /* Character generator */ - int s; - struct servtab *sep; -{ - struct sockaddr_in sin; - static char *rs; - int len, size; - char text[LINESIZ+2]; - - if (endring == 0) { - initring(); - rs = ring; - } - - size = sizeof(sin); - if (recvfrom(s, text, sizeof(text), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - if ((len = endring - rs) >= LINESIZ) - memmove(text, rs, LINESIZ); - else { - memmove(text, rs, len); - memmove(text + len, ring, LINESIZ - len); - } - if (++rs == endring) - rs = ring; - text[LINESIZ] = '\r'; - text[LINESIZ + 1] = '\n'; - (void) sendto(s, text, sizeof(text), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - -/* - * Return a machine readable date and time, in the form of the - * number of seconds since midnight, Jan 1, 1900. Since gettimeofday - * returns the number of seconds since midnight, Jan 1, 1970, - * we must add 2208988800 seconds to this figure to make up for - * some seventy years Bell Labs was asleep. - */ - -unsigned long -machtime() -{ - struct timeval tv; - - if (gettimeofday(&tv, (struct timezone *)NULL) < 0) { - if (debug) - warnx("unable to get time of day"); - return (0L); - } -#define OFFSET ((u_long)25567 * 24*60*60) - return (htonl((long)(tv.tv_sec + OFFSET))); -#undef OFFSET -} - -/* ARGSUSED */ -void -machtime_stream(s, sep) - int s; - struct servtab *sep; -{ - unsigned long result; - - result = machtime(); - (void) write(s, (char *) &result, sizeof(result)); -} - -/* ARGSUSED */ -void -machtime_dg(s, sep) - int s; - struct servtab *sep; -{ - unsigned long result; - struct sockaddr_in sin; - int size; - - size = sizeof(sin); - if (recvfrom(s, (char *)&result, sizeof(result), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - result = machtime(); - (void) sendto(s, (char *) &result, sizeof(result), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - -/* ARGSUSED */ -void -daytime_stream(s, sep) /* Return human-readable time of day */ - int s; - struct servtab *sep; -{ - char buffer[256]; - time_t clock; - - clock = time((time_t *) 0); - - (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); - (void) write(s, buffer, strlen(buffer)); -} - -/* ARGSUSED */ -void -daytime_dg(s, sep) /* Return human-readable time of day */ - int s; - struct servtab *sep; -{ - char buffer[256]; - time_t clock; - struct sockaddr_in sin; - int size; - - clock = time((time_t *) 0); - - size = sizeof(sin); - if (recvfrom(s, buffer, sizeof(buffer), 0, - (struct sockaddr *)&sin, &size) < 0) - return; - - if (check_loop(&sin, sep)) - return; - - (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); - (void) sendto(s, buffer, strlen(buffer), 0, - (struct sockaddr *)&sin, sizeof(sin)); -} - /* * print_service: * Dump relevant information to stderr @@ -2042,94 +1555,6 @@ print_service(action, sep) (void *) sep->se_bi, sep->se_server); } -/* - * Based on TCPMUX.C by Mark K. Lottor November 1988 - * sri-nic::ps:tcpmux.c - */ - - -static int /* # of characters upto \r,\n or \0 */ -getline(fd, buf, len) - int fd; - char *buf; - int len; -{ - int count = 0, n; - struct sigaction sa; - - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - sa.sa_handler = SIG_DFL; - sigaction(SIGALRM, &sa, (struct sigaction *)0); - do { - alarm(10); - n = read(fd, buf, len-count); - alarm(0); - if (n == 0) - return (count); - if (n < 0) - return (-1); - while (--n >= 0) { - if (*buf == '\r' || *buf == '\n' || *buf == '\0') - return (count); - count++; - buf++; - } - } while (count < len); - return (count); -} - -#define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ - -#define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) - -struct servtab * -tcpmux(s) - int s; -{ - struct servtab *sep; - char service[MAX_SERV_LEN+1]; - int len; - - /* Get requested service name */ - if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { - strwrite(s, "-Error reading service name\r\n"); - return (NULL); - } - service[len] = '\0'; - - if (debug) - warnx("tcpmux: someone wants %s", service); - - /* - * Help is a required command, and lists available services, - * one per line. - */ - if (!strcasecmp(service, "help")) { - for (sep = servtab; sep; sep = sep->se_next) { - if (!ISMUX(sep)) - continue; - (void)write(s,sep->se_service,strlen(sep->se_service)); - strwrite(s, "\r\n"); - } - return (NULL); - } - - /* Try matching a service in inetd.conf with the request */ - for (sep = servtab; sep; sep = sep->se_next) { - if (!ISMUX(sep)) - continue; - if (!strcasecmp(service, sep->se_service)) { - if (ISMUXPLUS(sep)) { - strwrite(s, "+Go\r\n"); - } - return (sep); - } - } - strwrite(s, "-Service not available\r\n"); - return (NULL); -} - #define CPMHSIZE 256 #define CPMHMASK (CPMHSIZE-1) #define CHTGRAN 10 diff --git a/usr.sbin/inetd/inetd.h b/usr.sbin/inetd/inetd.h new file mode 100644 index 0000000..1ec4a18 --- /dev/null +++ b/usr.sbin/inetd/inetd.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 1983, 1991, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include +#include + +#include + +#include + +#define BUFSIZE 8192 +#define LINESIZ 72 + +#define NORM_TYPE 0 +#define MUX_TYPE 1 +#define MUXPLUS_TYPE 2 +#define TTCP_TYPE 3 +#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ + ((sep)->se_type == MUXPLUS_TYPE)) +#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) +#define ISTTCP(sep) ((sep)->se_type == TTCP_TYPE) + +struct servtab { + char *se_service; /* name of service */ + int se_socktype; /* type of socket to use */ + char *se_proto; /* protocol used */ + int se_maxchild; /* max number of children */ + int se_maxcpm; /* max connects per IP per minute */ + int se_numchild; /* current number of children */ + pid_t *se_pids; /* array of child pids */ + char *se_user; /* user name to run as */ + char *se_group; /* group name to run as */ +#ifdef LOGIN_CAP + char *se_class; /* login class name to run with */ +#endif + struct biltin *se_bi; /* if built-in, description */ + char *se_server; /* server program */ + char *se_server_name; /* server program without path */ +#define MAXARGV 20 + char *se_argv[MAXARGV+1]; /* program arguments */ + int se_fd; /* open descriptor */ + struct sockaddr_in se_ctrladdr;/* bound address */ + u_char se_type; /* type: normal, mux, or mux+ */ + u_char se_checked; /* looked at during merge */ + u_char se_accept; /* i.e., wait/nowait mode */ + u_char se_rpc; /* ==1 if RPC service */ + int se_rpc_prog; /* RPC program number */ + u_int se_rpc_lowvers; /* RPC low version */ + u_int se_rpc_highvers; /* RPC high version */ + int se_count; /* number started since se_time */ + struct timeval se_time; /* start of se_count */ + struct servtab *se_next; +}; + +void chargen_dg __P((int, struct servtab *)); +void chargen_stream __P((int, struct servtab *)); +void close_sep __P((struct servtab *)); +void flag_signal __P((char)); +void flag_config __P((int)); +void config __P((void)); +void daytime_dg __P((int, struct servtab *)); +void daytime_stream __P((int, struct servtab *)); +void discard_dg __P((int, struct servtab *)); +void discard_stream __P((int, struct servtab *)); +void echo_dg __P((int, struct servtab *)); +void echo_stream __P((int, struct servtab *)); +void endconfig __P((void)); +struct servtab *enter __P((struct servtab *)); +void freeconfig __P((struct servtab *)); +struct servtab *getconfigent __P((void)); +void iderror __P((int, int, FILE *, int)); +void ident_stream __P((int, struct servtab *)); +void machtime_dg __P((int, struct servtab *)); +void machtime_stream __P((int, struct servtab *)); +int matchservent __P((char *, char *, char *)); +char *newstr __P((char *)); +char *nextline __P((FILE *)); +void print_service __P((char *, struct servtab *)); +void addchild __P((struct servtab *, int)); +void flag_reapchild __P((int)); +void reapchild __P((void)); +void enable __P((struct servtab *)); +void disable __P((struct servtab *)); +void flag_retry __P((int)); +void retry __P((void)); +int setconfig __P((void)); +void setup __P((struct servtab *)); +char *sskip __P((char **)); +char *skip __P((char **)); +struct servtab *tcpmux __P((int)); +int cpmip __P((struct servtab *, int)); +void inetd_setproctitle __P((char *, int)); + +void unregisterrpc __P((register struct servtab *sep)); + +struct biltin { + char *bi_service; /* internally provided service name */ + int bi_socktype; /* type of socket supported */ + short bi_fork; /* 1 if should fork before call */ + int bi_maxchild; /* max number of children, -1=default */ + void (*bi_fn)(); /* function which performs it */ +}; -- cgit v1.1