⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nsplitd.c

📁 xen 3.2.2 源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *	nsplitd.c *	--------- * * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ * * Copyright (c) 1995, University of Cambridge Computer Laboratory, * Copyright (c) 1995, Richard Black, All Rights Reserved. * * * A complete re-implementation of DME's nsplitd for use from inetd * *//* The basic stream comes in (via inetd) and we then conenct to * somewhere else providing a loop-through service, except we offer * two other ports for connection - one of which gets a second channel * using the top bit to distinguish, and the other is a master control * port (normally used for gdb) which gets complete exclusive access * for its duration. * * Originally designed for multiplexing a xwcons/telnet with a gdb * post-mortem debugging session. * * Here is a picture: * * 					    port0 (from inetd) *      8-bit connection     	       	   / * 	   made by us	   <----> nsplitd <-----gdbport (default port0+2) * 	to host:port/tcp		  |\ * 					  | port1 (default port0+1) *                                         \ *                                          control (default port0+3) * * If port1 is explicitly disabled (through a command-line option) then * port0 becomes 8-bit clean. *//* * N.B.: We do NOT support 8 bit stdin/stdout usage on a * /dev/... because to do that right involves much messing with ioctl * and TIOC... etc.  If you want to do that sort of thing then the * right way to do it is to chain this onto wconsd (which does know * about and understand all the ioctl and TIOC grief). */#include <sys/types.h>#include <stdarg.h>#include <stdio.h>#include <stdlib.h>#include <assert.h>#include <errno.h>#include <unistd.h>#include <ctype.h>#include <netdb.h>#include <string.h>#include <sys/time.h>#include <sys/signal.h>#include <sys/socket.h>#include <netinet/in.h>#include <netinet/tcp.h>#include <arpa/inet.h>#include <sys/ioctl.h>#include <syslog.h>#ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1#endif#ifndef LOG_DAEMON#define LOG_DAEMON 0#endif#define DB(x)  /* ((x), fflush(stderr)) */extern char *optarg;extern int optind, opterr, optopt;static char *prog_name;static void usage(void){    fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n",	    prog_name);    fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]"	    "[-c<ctlport>][-8] host:service\n",	    prog_name);    exit(1);}static void fault(char *format, ...){    va_list		ap;    char		logbuf[1024];    va_start(ap, format);    fprintf(stderr, "%s: ", prog_name);    vfprintf(stderr, format, ap);    fflush(stderr);    va_end(ap);        /* XXX This is a bit dubious, but there is no vsyslog */    va_start(ap, format);    vsprintf(logbuf, format, ap);    syslog(LOG_ERR, logbuf);    va_end(ap);    exit(1);}static int getservice(char *name, unsigned short *port){    struct servent		*se;    if (!name) return -1;    if (isdigit(name[0]))	*port = atoi(name);    else    {	if (!(se = getservbyname(name, "tcp")))	    return -1;	*port = ntohs(se->s_port);    }    return 0;}/*  *  connect_host: connect to ("name", "port") */static int connect_host (char *name, unsigned int port){    int			fd;    struct hostent	*hostent;    struct sockaddr_in	sin;    int			on;        if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)	fault("socket");        if (!(hostent = gethostbyname(name)))	fault("gethostbyname: %s: %s\n", name, strerror(errno));        memset(&sin, 0, sizeof(sin));    sin.sin_family = AF_INET;    sin.sin_port   = htons (port);    memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr));        if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0)	fault("connect: %s:%u: %s\n", name, port, strerror(errno));        on = 1;    if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0)	syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m");    on = 1;    if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0)	syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");    return fd;}/* * open a tcp socket and start listening for connections on it */static int startlistening(unsigned short port){    int			fd, on;    struct sockaddr_in	sin;    if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0)	fault("socket");        on = 1;    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)      syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m");    memset(&sin, 0, sizeof(sin));    sin.sin_family      = AF_INET;    sin.sin_port        = htons (port);    sin.sin_addr.s_addr = INADDR_ANY;    if (bind(fd, &sin, sizeof(sin)) < 0)	fault("bind: %u: %s\n", port, strerror(errno));        if (listen(fd, 1) < 0)	fault("listen: %s\n", strerror(errno));        return fd;}static void noblock(int fd){    int on=1;        if (ioctl(fd, FIONBIO, &on) < 0)	fault("ioctl: FIONBIO: %s\n", strerror(errno));}/* You might not believe this, but fd_sets don't have to be a 32-bit * integer.  In particular, in glibc2 it is an array of unsigned * longs.  Hence, this hacked up FD_SET_rjb() that works out if it * would have been a nop. */#define FD_SET_rjb(fd, setp) \do {						\    if ((fd) != 32)				\	FD_SET((fd), (setp));			\} while(0)#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0)#define MAXSIZE	256/* ----------------------------------------------------------------- * The main bit of the algorithm. Note we use 32 to mean not connected * because this gives us 1<<32 == 0. We could have done this one * character at a time, but that would have been very inefficient and * not the unix way.  */static int debug;static void doit(int actl, int acto, int lish, int lisg, int lisc){    int		acth, actg, actc;    int		gdbmode = FALSE;    char	gibuf[MAXSIZE], oibuf[MAXSIZE];    char	libuf[MAXSIZE], lobuf[MAXSIZE];    char	hibuf[MAXSIZE], hobuf[MAXSIZE];    char	ctlbuf[MAXSIZE];    fd_set	rdfs, wrfs, exfs;    int		gicc, oicc, licc, locc, hicc, hocc, ctlcc;    char	*giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr;    int		rc, fromlen;    struct sockaddr_in		from;        gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0;    acth = actg = actc = 32;			/* XXX yummy */    noblock(actl);    noblock(acto);    for(;;)    {	FD_ZERO(&rdfs);	FD_ZERO(&wrfs);	FD_ZERO(&exfs);	/* always take input from the control port (if it's connected) */	FD_SET_rjb(actc, &rdfs);	if (gdbmode)	{	    if (oicc)		FD_SET_rjb(actg, &wrfs);	    else		FD_SET_rjb(acto, &rdfs);	    	    if (gicc)		FD_SET_rjb(acto, &wrfs);	    else		FD_SET_rjb(actg, &rdfs);	}	else	{	    /* There is no such thing as oibuf because its been split into	     * lobuf and hobuf	     */	    if (locc || hocc)	    {		if (locc)		    FD_SET_rjb(actl, &wrfs);		if (hocc)		    FD_SET_rjb(acth, &wrfs);	    }	    else		FD_SET_rjb(acto, &rdfs);	    	    if (licc)		FD_SET_rjb(acto, &wrfs);	    else		FD_SET_rjb(actl, &rdfs);	    	    if (hicc)		FD_SET_rjb(acto, &wrfs);	    else		FD_SET_rjb(acth, &rdfs);	}		if (acth == 32 && lish>=0)	FD_SET_rjb(lish, &rdfs);	if (actg == 32)			FD_SET_rjb(lisg, &rdfs);	if (actc == 32)			FD_SET_rjb(lisc, &rdfs);	/* now make exfs the union of the read and write fd sets, plus	 * "actl" */	{	    int i;	    exfs = rdfs;	    for(i=0; i<32; i++)  /* XXX we only copy fd numbers up to 31 */		if (FD_ISSET(i, &wrfs))		    FD_SET_rjb(i, &exfs);	    FD_SET_rjb(actl, &exfs);	}	/* XXX AND: can't print something of type fd_set as %x - it         * might be an array */	DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n",		   prog_name, rdfs, wrfs, exfs));		if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0)	    fault("select: %s\n", strerror(errno));		DB(fprintf(stderr, "%s: after  select: %08x %08x %08x\n",		   prog_name, rdfs, wrfs, exfs));		/* XXX it appears that a non-blocking socket may not show up	 * correctly in exfs but instead goes readable with no data in	 * it. Thus we check for zero and goto the appropriate close	 * method.  */	/* Deal with exceptions */	if (FD_ISSET_rjb(actg, &exfs))	{	exfs_actg:	    close(actg);	    gdbmode = FALSE;	    oicc = 0;	    oiptr = oibuf;	    actg = 32;	    continue;		/* because assumptions changed */	}	if (FD_ISSET_rjb(acth, &exfs))	{	exfs_acth:	    close(acth);	    hicc = hocc = 0;	    hiptr = hibuf;	    hoptr = hibuf;	    acth = 32;	    continue;		/* because assumptions changed */	}	if (FD_ISSET_rjb(actl, &exfs) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -