mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-29 21:26:51 +00:00
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 .
This commit is contained in:
parent
d49c1fb83f
commit
5ff3afce6f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=48981
|
@ -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
|
||||
|
||||
|
|
505
usr.sbin/inetd/builtins.c
Normal file
505
usr.sbin/inetd/builtins.c
Normal file
|
@ -0,0 +1,505 @@
|
|||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ucred.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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:<mkl>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);
|
||||
}
|
||||
|
|
@ -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 <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ucred.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
@ -119,7 +115,6 @@ static const char rcsid[] =
|
|||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
|
@ -136,6 +131,9 @@ static const char rcsid[] =
|
|||
#include <libutil.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
#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;
|
||||
struct servtab *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 }
|
||||
};
|
||||
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 <ctype.h>
|
||||
#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:<mkl>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
|
||||
|
|
134
usr.sbin/inetd/inetd.h
Normal file
134
usr.sbin/inetd/inetd.h
Normal file
|
@ -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 <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#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 */
|
||||
};
|
Loading…
Reference in a new issue