ia64/xen-unstable
changeset 1662:8f8449890369
bitkeeper revision 1.1041.6.1 (40e5221awCqaZfcsO_ny2z3p_6BiEg)
nsplitd.c, Makefile:
mvdir
Makefile:
Rename: BitKeeper/deleted/.del-Makefile~9f548ce6ff509eac -> tools/nsplitd/Makefile
nsplitd.c:
Rename: BitKeeper/deleted/.del-nsplitd.c~8b67653f8e377176 -> tools/nsplitd/nsplitd.c
nsplitd.c, Makefile:
mvdir
Makefile:
Rename: BitKeeper/deleted/.del-Makefile~9f548ce6ff509eac -> tools/nsplitd/Makefile
nsplitd.c:
Rename: BitKeeper/deleted/.del-nsplitd.c~8b67653f8e377176 -> tools/nsplitd/nsplitd.c
author | kaf24@scramble.cl.cam.ac.uk |
---|---|
date | Fri Jul 02 08:51:38 2004 +0000 (2004-07-02) |
parents | d9a96380ff94 |
children | 23e371e87d2f |
files | .rootkeys tools/misc/nsplitd/Makefile tools/misc/nsplitd/nsplitd.c |
line diff
1.1 --- a/.rootkeys Thu Jul 01 23:32:40 2004 +0000 1.2 +++ b/.rootkeys Fri Jul 02 08:51:38 2004 +0000 1.3 @@ -201,6 +201,8 @@ 3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/mis 1.4 3f6dc140C8tAeBfroAF24VrmCS4v_w tools/misc/miniterm/README 1.5 3f6dc142IHaf6XIcAYGmhV9nNSIHFQ tools/misc/miniterm/miniterm.c 1.6 40c9c469kT0H9COWzA4XzPBjWK0WsA tools/misc/netfix 1.7 +4022a73cEKvrYe_DVZW2JlAxobg9wg tools/misc/nsplitd/Makefile 1.8 +4022a73cKms4Oq030x2JBzUB426lAQ tools/misc/nsplitd/nsplitd.c 1.9 3f870808_8aFBAcZbWiWGdgrGQyIEw tools/misc/p4perf.h 1.10 3f5ef5a2ir1kVAthS14Dc5QIRCEFWg tools/misc/xen-clone 1.11 3f5ef5a2dTZP0nnsFoeq2jRf3mWDDg tools/misc/xen-clone.README
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/tools/misc/nsplitd/Makefile Fri Jul 02 08:51:38 2004 +0000 2.3 @@ -0,0 +1,22 @@ 2.4 + 2.5 +CC = gcc 2.6 +CFLAGS = -Wall -O3 2.7 +CFILES = $(wildcard *.c) 2.8 + 2.9 +HDRS = $(wildcard *.h) 2.10 +OBJS = $(patsubst %.c,%.o,$(wildcard *.c)) 2.11 + 2.12 +TARGET = nsplitd 2.13 + 2.14 +all: $(TARGET) 2.15 + 2.16 +install: all 2.17 + 2.18 +clean: 2.19 + $(RM) *.o $(TARGET) *~ 2.20 + 2.21 +$(TARGET): $(OBJS) 2.22 + $(CC) $(CFLAGS) -o $@ $^ 2.23 + 2.24 +%.o: %.c $(HDRS) Makefile 2.25 + $(CC) $(CFLAGS) -c -o $@ $<
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/tools/misc/nsplitd/nsplitd.c Fri Jul 02 08:51:38 2004 +0000 3.3 @@ -0,0 +1,686 @@ 3.4 +/* 3.5 + * nsplitd.c 3.6 + * --------- 3.7 + * 3.8 + * $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ 3.9 + * 3.10 + * Copyright (c) 1995, University of Cambridge Computer Laboratory, 3.11 + * Copyright (c) 1995, Richard Black, All Rights Reserved. 3.12 + * 3.13 + * 3.14 + * A complete re-implementation of DME's nsplitd for use from inetd 3.15 + * 3.16 + */ 3.17 + 3.18 +/* The basic stream comes in (via inetd) and we then conenct to 3.19 + * somewhere else providing a loop-through service, except we offer 3.20 + * two other ports for connection - one of which gets a second channel 3.21 + * using the top bit to distinguish, and the other is a master control 3.22 + * port (normally used for gdb) which gets complete exclusive access 3.23 + * for its duration. 3.24 + * 3.25 + * Originally designed for multiplexing a xwcons/telnet with a gdb 3.26 + * post-mortem debugging session. 3.27 + * 3.28 + * Here is a picture: 3.29 + * 3.30 + * port0 (from inetd) 3.31 + * 8-bit connection / 3.32 + * made by us <----> nsplitd <-----gdbport (default port0+2) 3.33 + * to host:port/tcp |\ 3.34 + * | port1 (default port0+1) 3.35 + * \ 3.36 + * control (default port0+3) 3.37 + * 3.38 + * If port1 is explicitly disabled (through a command-line option) then 3.39 + * port0 becomes 8-bit clean. 3.40 + */ 3.41 + 3.42 +/* 3.43 + * N.B.: We do NOT support 8 bit stdin/stdout usage on a 3.44 + * /dev/... because to do that right involves much messing with ioctl 3.45 + * and TIOC... etc. If you want to do that sort of thing then the 3.46 + * right way to do it is to chain this onto wconsd (which does know 3.47 + * about and understand all the ioctl and TIOC grief). 3.48 + */ 3.49 + 3.50 +#include <sys/types.h> 3.51 +#include <stdarg.h> 3.52 +#include <stdio.h> 3.53 +#include <stdlib.h> 3.54 +#include <assert.h> 3.55 +#include <errno.h> 3.56 +#include <unistd.h> 3.57 +#include <ctype.h> 3.58 +#include <netdb.h> 3.59 +#include <string.h> 3.60 + 3.61 +#include <sys/time.h> 3.62 +#include <sys/signal.h> 3.63 +#include <sys/socket.h> 3.64 +#include <netinet/in.h> 3.65 +#include <netinet/tcp.h> 3.66 +#include <arpa/inet.h> 3.67 +#include <sys/ioctl.h> 3.68 +#include <syslog.h> 3.69 + 3.70 +#ifndef FALSE 3.71 +#define FALSE 0 3.72 +#endif 3.73 +#ifndef TRUE 3.74 +#define TRUE 1 3.75 +#endif 3.76 + 3.77 +#ifndef LOG_DAEMON 3.78 +#define LOG_DAEMON 0 3.79 +#endif 3.80 + 3.81 +#define DB(x) /* ((x), fflush(stderr)) */ 3.82 + 3.83 +extern char *optarg; 3.84 + 3.85 +extern int optind, opterr, optopt; 3.86 + 3.87 +static char *prog_name; 3.88 + 3.89 +static void usage(void) 3.90 +{ 3.91 + fprintf(stderr, "This program (%s) should be run via inetd (tcp)\n\n", 3.92 + prog_name); 3.93 + fprintf(stderr, "usage: %s [-h<highport>][-g<gdbport>]" 3.94 + "[-c<ctlport>][-8] host:service\n", 3.95 + prog_name); 3.96 + exit(1); 3.97 +} 3.98 + 3.99 +static void fault(char *format, ...) 3.100 +{ 3.101 + va_list ap; 3.102 + char logbuf[1024]; 3.103 + 3.104 + va_start(ap, format); 3.105 + fprintf(stderr, "%s: ", prog_name); 3.106 + vfprintf(stderr, format, ap); 3.107 + fflush(stderr); 3.108 + va_end(ap); 3.109 + 3.110 + /* XXX This is a bit dubious, but there is no vsyslog */ 3.111 + va_start(ap, format); 3.112 + vsprintf(logbuf, format, ap); 3.113 + syslog(LOG_ERR, logbuf); 3.114 + va_end(ap); 3.115 + exit(1); 3.116 +} 3.117 + 3.118 +static int getservice(char *name, unsigned short *port) 3.119 +{ 3.120 + struct servent *se; 3.121 + 3.122 + if (!name) return -1; 3.123 + 3.124 + if (isdigit(name[0])) 3.125 + *port = atoi(name); 3.126 + else 3.127 + { 3.128 + if (!(se = getservbyname(name, "tcp"))) 3.129 + return -1; 3.130 + *port = ntohs(se->s_port); 3.131 + } 3.132 + return 0; 3.133 +} 3.134 + 3.135 +/* 3.136 + * connect_host: connect to ("name", "port") 3.137 + */ 3.138 +static int connect_host (char *name, unsigned int port) 3.139 +{ 3.140 + int fd; 3.141 + struct hostent *hostent; 3.142 + struct sockaddr_in sin; 3.143 + int on; 3.144 + 3.145 + if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) 3.146 + fault("socket"); 3.147 + 3.148 + if (!(hostent = gethostbyname(name))) 3.149 + fault("gethostbyname: %s: %s\n", name, strerror(errno)); 3.150 + 3.151 + memset(&sin, 0, sizeof(sin)); 3.152 + sin.sin_family = AF_INET; 3.153 + sin.sin_port = htons (port); 3.154 + memcpy(&sin.sin_addr.s_addr, hostent->h_addr, sizeof(struct in_addr)); 3.155 + 3.156 + if (connect(fd, (struct sockaddr *) &sin, sizeof (sin)) < 0) 3.157 + fault("connect: %s:%u: %s\n", name, port, strerror(errno)); 3.158 + 3.159 + on = 1; 3.160 + if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) 3.161 + syslog(LOG_WARNING, "setsockopt (TCP_NODELAY): %m"); 3.162 + 3.163 + on = 1; 3.164 + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 3.165 + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 3.166 + 3.167 + return fd; 3.168 +} 3.169 + 3.170 +/* 3.171 + * open a tcp socket and start listening for connections on it 3.172 + */ 3.173 +static int startlistening(unsigned short port) 3.174 +{ 3.175 + int fd, on; 3.176 + struct sockaddr_in sin; 3.177 + 3.178 + if ((fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) 3.179 + fault("socket"); 3.180 + 3.181 + on = 1; 3.182 + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0) 3.183 + syslog(LOG_WARNING, "setsockopt (SO_REUSEADDR): %m"); 3.184 + 3.185 + memset(&sin, 0, sizeof(sin)); 3.186 + sin.sin_family = AF_INET; 3.187 + sin.sin_port = htons (port); 3.188 + sin.sin_addr.s_addr = INADDR_ANY; 3.189 + if (bind(fd, &sin, sizeof(sin)) < 0) 3.190 + fault("bind: %u: %s\n", port, strerror(errno)); 3.191 + 3.192 + if (listen(fd, 1) < 0) 3.193 + fault("listen: %s\n", strerror(errno)); 3.194 + 3.195 + return fd; 3.196 +} 3.197 + 3.198 +static void noblock(int fd) 3.199 +{ 3.200 + int on=1; 3.201 + 3.202 + if (ioctl(fd, FIONBIO, &on) < 0) 3.203 + fault("ioctl: FIONBIO: %s\n", strerror(errno)); 3.204 +} 3.205 + 3.206 + 3.207 +/* You might not believe this, but fd_sets don't have to be a 32-bit 3.208 + * integer. In particular, in glibc2 it is an array of unsigned 3.209 + * longs. Hence, this hacked up FD_SET_rjb() that works out if it 3.210 + * would have been a nop. */ 3.211 +#define FD_SET_rjb(fd, setp) \ 3.212 +do { \ 3.213 + if ((fd) != 32) \ 3.214 + FD_SET((fd), (setp)); \ 3.215 +} while(0) 3.216 + 3.217 +#define FD_ISSET_rjb(fd, setp) (((fd) != 32)? FD_ISSET((fd), (setp)) : 0) 3.218 + 3.219 +#define MAXSIZE 256 3.220 + 3.221 +/* ----------------------------------------------------------------- 3.222 + * The main bit of the algorithm. Note we use 32 to mean not connected 3.223 + * because this gives us 1<<32 == 0. We could have done this one 3.224 + * character at a time, but that would have been very inefficient and 3.225 + * not the unix way. */ 3.226 +static int debug; 3.227 + 3.228 +static void doit(int actl, int acto, int lish, int lisg, int lisc) 3.229 +{ 3.230 + int acth, actg, actc; 3.231 + int gdbmode = FALSE; 3.232 + char gibuf[MAXSIZE], oibuf[MAXSIZE]; 3.233 + char libuf[MAXSIZE], lobuf[MAXSIZE]; 3.234 + char hibuf[MAXSIZE], hobuf[MAXSIZE]; 3.235 + char ctlbuf[MAXSIZE]; 3.236 + fd_set rdfs, wrfs, exfs; 3.237 + int gicc, oicc, licc, locc, hicc, hocc, ctlcc; 3.238 + char *giptr, *oiptr, *liptr, *loptr, *hiptr, *hoptr; 3.239 + int rc, fromlen; 3.240 + struct sockaddr_in from; 3.241 + 3.242 + gicc = oicc = licc = locc = hicc = hocc = ctlcc = 0; 3.243 + acth = actg = actc = 32; /* XXX yummy */ 3.244 + 3.245 + noblock(actl); 3.246 + noblock(acto); 3.247 + 3.248 + for(;;) 3.249 + { 3.250 + FD_ZERO(&rdfs); 3.251 + FD_ZERO(&wrfs); 3.252 + FD_ZERO(&exfs); 3.253 + 3.254 + /* always take input from the control port (if it's connected) */ 3.255 + FD_SET_rjb(actc, &rdfs); 3.256 + 3.257 + if (gdbmode) 3.258 + { 3.259 + if (oicc) 3.260 + FD_SET_rjb(actg, &wrfs); 3.261 + else 3.262 + FD_SET_rjb(acto, &rdfs); 3.263 + 3.264 + if (gicc) 3.265 + FD_SET_rjb(acto, &wrfs); 3.266 + else 3.267 + FD_SET_rjb(actg, &rdfs); 3.268 + } 3.269 + else 3.270 + { 3.271 + /* There is no such thing as oibuf because its been split into 3.272 + * lobuf and hobuf 3.273 + */ 3.274 + if (locc || hocc) 3.275 + { 3.276 + if (locc) 3.277 + FD_SET_rjb(actl, &wrfs); 3.278 + if (hocc) 3.279 + FD_SET_rjb(acth, &wrfs); 3.280 + } 3.281 + else 3.282 + FD_SET_rjb(acto, &rdfs); 3.283 + 3.284 + if (licc) 3.285 + FD_SET_rjb(acto, &wrfs); 3.286 + else 3.287 + FD_SET_rjb(actl, &rdfs); 3.288 + 3.289 + if (hicc) 3.290 + FD_SET_rjb(acto, &wrfs); 3.291 + else 3.292 + FD_SET_rjb(acth, &rdfs); 3.293 + } 3.294 + 3.295 + if (acth == 32 && lish>=0) FD_SET_rjb(lish, &rdfs); 3.296 + if (actg == 32) FD_SET_rjb(lisg, &rdfs); 3.297 + if (actc == 32) FD_SET_rjb(lisc, &rdfs); 3.298 + 3.299 + /* now make exfs the union of the read and write fd sets, plus 3.300 + * "actl" */ 3.301 + { 3.302 + int i; 3.303 + exfs = rdfs; 3.304 + for(i=0; i<32; i++) /* XXX we only copy fd numbers up to 31 */ 3.305 + if (FD_ISSET(i, &wrfs)) 3.306 + FD_SET_rjb(i, &exfs); 3.307 + FD_SET_rjb(actl, &exfs); 3.308 + } 3.309 + 3.310 + /* XXX AND: can't print something of type fd_set as %x - it 3.311 + * might be an array */ 3.312 + DB(fprintf(stderr, "%s: before select: %08x %08x %08x\n", 3.313 + prog_name, rdfs, wrfs, exfs)); 3.314 + 3.315 + if (select(32, &rdfs, &wrfs, &exfs, NULL) < 0) 3.316 + fault("select: %s\n", strerror(errno)); 3.317 + 3.318 + DB(fprintf(stderr, "%s: after select: %08x %08x %08x\n", 3.319 + prog_name, rdfs, wrfs, exfs)); 3.320 + 3.321 + /* XXX it appears that a non-blocking socket may not show up 3.322 + * correctly in exfs but instead goes readable with no data in 3.323 + * it. Thus we check for zero and goto the appropriate close 3.324 + * method. */ 3.325 + 3.326 + /* Deal with exceptions */ 3.327 + if (FD_ISSET_rjb(actg, &exfs)) 3.328 + { 3.329 + exfs_actg: 3.330 + close(actg); 3.331 + gdbmode = FALSE; 3.332 + oicc = 0; 3.333 + oiptr = oibuf; 3.334 + actg = 32; 3.335 + continue; /* because assumptions changed */ 3.336 + } 3.337 + if (FD_ISSET_rjb(acth, &exfs)) 3.338 + { 3.339 + exfs_acth: 3.340 + close(acth); 3.341 + hicc = hocc = 0; 3.342 + hiptr = hibuf; 3.343 + hoptr = hibuf; 3.344 + acth = 32; 3.345 + continue; /* because assumptions changed */ 3.346 + } 3.347 + if (FD_ISSET_rjb(actl, &exfs) || 3.348 + FD_ISSET_rjb(acto, &exfs)) 3.349 + { 3.350 + exfs_actl: 3.351 + exfs_acto: 3.352 + /* Thats all folks ... */ 3.353 + break; 3.354 + } 3.355 + if (FD_ISSET_rjb(actc, &exfs)) 3.356 + { 3.357 + exfs_ctl: 3.358 + close(actc); 3.359 + actc = 32; 3.360 + ctlcc = 0; 3.361 + continue; 3.362 + } 3.363 + 3.364 + /* Deal with reading */ 3.365 + if (FD_ISSET_rjb(acto, &rdfs)) 3.366 + { 3.367 + if ((oicc = read(acto, oiptr = oibuf, MAXSIZE)) < 0) 3.368 + fault("read acto: %d: %s\n", oicc, strerror(errno)); 3.369 + if (!oicc) goto exfs_acto; 3.370 + 3.371 + if (!gdbmode) 3.372 + { 3.373 + int t; 3.374 + 3.375 + assert((locc == 0) && (hocc == 0)); 3.376 + loptr = lobuf; 3.377 + hoptr = hobuf; 3.378 + 3.379 + if (lish>=0) { 3.380 + for(t=0; t<oicc; t++) 3.381 + if (oibuf[t] & 0x80) 3.382 + hobuf[hocc++] = oibuf[t] & 0x7f; 3.383 + else 3.384 + lobuf[locc++] = oibuf[t]; 3.385 + } else { 3.386 + for (t=0; t<oicc; t++) 3.387 + lobuf[locc++] = oibuf[t]; 3.388 + } 3.389 + /* If no high connection scratch that */ 3.390 + if (acth == 32) 3.391 + hocc=0; 3.392 + } 3.393 + } 3.394 + if (FD_ISSET_rjb(actl, &rdfs)) 3.395 + { 3.396 + if ((licc = read(actl, liptr = libuf, MAXSIZE)) < 0) 3.397 + fault("read actl: %d: %s\n", licc, strerror(errno)); 3.398 + if (!licc) goto exfs_actl; 3.399 + } 3.400 + if (FD_ISSET_rjb(acth, &rdfs)) 3.401 + { 3.402 + int t; 3.403 + 3.404 + if ((hicc = read(acth, hiptr = hibuf, MAXSIZE)) < 0) 3.405 + fault("read acth: %d: %s\n", hicc, strerror(errno)); 3.406 + if (!hicc) goto exfs_acth; 3.407 + for(t=0; t<hicc; t++) 3.408 + hibuf[t] |= 0x80; 3.409 + } 3.410 + if (FD_ISSET_rjb(actg, &rdfs)) 3.411 + { 3.412 + if ((gicc = read(actg, giptr = gibuf, MAXSIZE)) < 0) 3.413 + fault("read actg: %d: %s\n", gicc, strerror(errno)); 3.414 + if (debug) write(1, giptr, gicc); /* XXX */ 3.415 + if (!gicc) goto exfs_actg; 3.416 + } 3.417 + if (FD_ISSET_rjb(actc, &rdfs)) 3.418 + { 3.419 + if ((ctlcc = read(actc, ctlbuf, MAXSIZE)) < 0) 3.420 + fault("read actc: %d: %s\n", ctlcc, strerror(errno)); 3.421 + if (debug) write(1, ctlbuf, gicc); 3.422 + if (!ctlcc) goto exfs_ctl; 3.423 + if (ctlbuf[0] == 'r') /* reset command */ 3.424 + { 3.425 + syslog(LOG_INFO, "reset command read, exiting"); 3.426 + if (debug) write(1, "reseting\n", sizeof("reseting\n")); 3.427 + break; 3.428 + } 3.429 + } 3.430 + 3.431 + /* Deal with writing */ 3.432 + if (FD_ISSET_rjb(actg, &wrfs)) 3.433 + { 3.434 + /* We must be in gdb mode so send oi buffer data */ 3.435 + assert(gdbmode); 3.436 + if (debug) write(2, oiptr, oicc); /* XXX */ 3.437 + if ((rc = write(actg, oiptr, oicc)) <= 0) 3.438 + fault("write actg: %d: %s\n", rc, strerror(errno)); 3.439 + oiptr += rc; 3.440 + oicc -= rc; 3.441 + } 3.442 + if (FD_ISSET_rjb(actl, &wrfs)) 3.443 + { 3.444 + if ((rc = write(actl, loptr, locc)) <= 0) 3.445 + fault("write actl: %d: %s\n", rc, strerror(errno)); 3.446 + loptr += rc; 3.447 + locc -= rc; 3.448 + } 3.449 + if (FD_ISSET_rjb(acth, &wrfs)) 3.450 + { 3.451 + if ((rc = write(acth, hoptr, hocc)) <= 0) 3.452 + fault("write acth: %d: %s\n", rc, strerror(errno)); 3.453 + hoptr += rc; 3.454 + hocc -= rc; 3.455 + } 3.456 + if (FD_ISSET_rjb(acto, &wrfs)) 3.457 + { 3.458 + /* If in gdb mode send gdb input, otherwise send low data 3.459 + preferentially */ 3.460 + if (gdbmode) 3.461 + { 3.462 + assert(gicc); 3.463 + if ((rc = write(acto, giptr, gicc)) <= 0) 3.464 + fault("write acto: %d: %s\n", rc, strerror(errno)); 3.465 + giptr += rc; 3.466 + gicc -= rc; 3.467 + } 3.468 + else 3.469 + { 3.470 + if (licc) 3.471 + { 3.472 + if ((rc = write(acto, liptr, licc)) <= 0) 3.473 + fault("write acto: %d: %s\n", rc, strerror(errno)); 3.474 + liptr += rc; 3.475 + licc -= rc; 3.476 + } 3.477 + else 3.478 + { 3.479 + assert(hicc); 3.480 + if ((rc = write(acto, hiptr, hicc)) <= 0) 3.481 + fault("write acto: %d: %s\n", rc, strerror(errno)); 3.482 + hiptr += rc; 3.483 + hicc -= rc; 3.484 + } 3.485 + } 3.486 + } 3.487 + 3.488 + /* Deals with new connections */ 3.489 + if ((acth == 32) && lish>=0 && (FD_ISSET_rjb(lish, &rdfs))) 3.490 + { 3.491 + fromlen = sizeof(from); 3.492 + if ((acth = accept(lish, &from, &fromlen)) < 0) 3.493 + { 3.494 + syslog(LOG_WARNING, "accept: %m"); 3.495 + acth = 32; 3.496 + } 3.497 + else 3.498 + { 3.499 + noblock(acth); 3.500 + hicc = hocc = 0; 3.501 + syslog(LOG_INFO, "highbit client peer is %s:%u\n", 3.502 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 3.503 + } 3.504 + } 3.505 + 3.506 + if ((actg == 32) && (FD_ISSET_rjb(lisg, &rdfs))) 3.507 + { 3.508 + fromlen = sizeof(from); 3.509 + if ((actg = accept(lisg, &from, &fromlen)) < 0) 3.510 + { 3.511 + syslog(LOG_WARNING, "accept: %m"); 3.512 + actg = 32; 3.513 + } 3.514 + else 3.515 + { 3.516 + noblock(actg); 3.517 + gicc = 0; 3.518 + gdbmode = TRUE; 3.519 + syslog(LOG_INFO, "gdb client peer is %s:%u\n", 3.520 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 3.521 + } 3.522 + } 3.523 + 3.524 + if ((actc == 32) && (FD_ISSET_rjb(lisc, &rdfs))) 3.525 + { 3.526 + fromlen = sizeof(from); 3.527 + if ((actc = accept(lisc, &from, &fromlen)) < 0) 3.528 + { 3.529 + syslog(LOG_WARNING, "accept (ctl): %m"); 3.530 + actc = 32; 3.531 + } 3.532 + else 3.533 + { 3.534 + noblock(actc); 3.535 + syslog(LOG_INFO, "ctl client peer is %s:%u\n", 3.536 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 3.537 + } 3.538 + } 3.539 + 3.540 + /* Back to top of loop */ 3.541 + } 3.542 + 3.543 + /* We are bailing because one of the primary connections has gone 3.544 + * away. We close these all explicitly here because that way the 3.545 + * timeout on reusing the port numbers is smnaller. */ 3.546 + 3.547 + close(acth); 3.548 + close(actg); 3.549 + /* XXX AND: why are we closing all these "character counts" ?? */ 3.550 + close(gicc); 3.551 + close(oicc); 3.552 + close(licc); 3.553 + close(locc); 3.554 + close(hicc); 3.555 + close(hocc); 3.556 +} 3.557 + 3.558 +/* 3.559 + * ------------------------------------------------------------ 3.560 + */ 3.561 +int main(int argc, char **argv) 3.562 +{ 3.563 + /* In general, suffix "l" is low channel, "h" is high channel, "g" 3.564 + * is gdb channel, "c" is control channel and "o" is output channel. 3.565 + */ 3.566 + struct sockaddr_in from; 3.567 + int infd = 0, outfd; 3.568 + unsigned short portl, porth, portg, portc, porto; 3.569 + int on = 1, c; 3.570 + char *outname, *outservice; 3.571 + int fromlen; 3.572 + int lish, lisg, lisc; 3.573 +#if 0 3.574 + FILE *newerr; 3.575 +#endif /* 0 */ 3.576 + 3.577 + prog_name = argv[0]; 3.578 + 3.579 + if (isatty(infd)) 3.580 + usage(); 3.581 + 3.582 + /* Here, then not just a simple idiot. */ 3.583 + 3.584 + signal(SIGPIPE, SIG_IGN); 3.585 + 3.586 + openlog(prog_name, LOG_PID, LOG_DAEMON); 3.587 + 3.588 + fromlen = sizeof(from); 3.589 + if (getsockname(infd, &from, &fromlen) < 0) 3.590 + fault("getsockname: %s", strerror(errno)); 3.591 + if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET)) 3.592 + fault("not an inet socket (family=%d)\n", from.sin_family); 3.593 + 3.594 + portl = ntohs(from.sin_port); 3.595 + porth = portl+1; 3.596 + portg = porth+1; 3.597 + portc = portg+1; 3.598 + 3.599 + fromlen = sizeof(from); 3.600 + if (getpeername(infd, &from, &fromlen) < 0) 3.601 + fault("getpeername: %s", strerror(errno)); 3.602 + if ((fromlen != sizeof(from)) || (from.sin_family != AF_INET)) 3.603 + fault("not an inet socket (family=%d)\n", from.sin_family); 3.604 + 3.605 + syslog(LOG_INFO, "on port %u peer is %s:%u\n", portl, 3.606 + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); 3.607 + 3.608 + if (setsockopt(infd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) 3.609 + syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 3.610 + 3.611 + /* from here on, we map stderr to output on the connection so we can 3.612 + * report errors to the remote user. 3.613 + */ 3.614 +#if 0 3.615 + if (!(newerr = fdopen(infd, "w"))) 3.616 + syslog(LOG_WARNING, "fdopen: %m"); 3.617 + else 3.618 + *stderr = *newerr; 3.619 +#endif 3.620 + 3.621 + while((c = getopt(argc, argv, "d8h:g:c:")) != EOF) 3.622 + { 3.623 + switch(c) 3.624 + { 3.625 + case 'd': 3.626 + debug++; 3.627 + break; 3.628 + 3.629 + case 'h': 3.630 + /* high bit port */ 3.631 + if (getservice(optarg, &porth) < 0) 3.632 + fault("getservice failed (high port '%s')\n", optarg); 3.633 + break; 3.634 + 3.635 + case 'g': 3.636 + /* gdb port */ 3.637 + if (getservice(optarg, &portg) < 0) 3.638 + fault("getservice failed (gdb port '%s')\n", optarg); 3.639 + break; 3.640 + 3.641 + case 'c': 3.642 + /* control port */ 3.643 + if (getservice(optarg, &portc) < 0) 3.644 + fault("getservice failed (control port '%s')\n", optarg); 3.645 + break; 3.646 + 3.647 + case '8': 3.648 + /* 8-bit clean; no high port */ 3.649 + porth=0; 3.650 + break; 3.651 + 3.652 + default: 3.653 + fault("bad argument list!\n"); 3.654 + } 3.655 + } 3.656 + 3.657 + if (argc != optind + 1) 3.658 + fault("unparsed arguments (%d!=%d)\n", argc, optind+1); 3.659 + 3.660 + outname = argv[optind]; 3.661 + if (!(outservice = strchr(outname, ':'))) 3.662 + fault("output arg '%s' doesn't contain ':'\n", outname); 3.663 + *outservice++ = 0; 3.664 + if (getservice(outservice, &porto) < 0) 3.665 + fault("getservice failed (output port '%s')\n", outservice); 3.666 + 3.667 + /* Time to start the sockets */ 3.668 + 3.669 + if (porth) { 3.670 + lish = startlistening(porth); 3.671 + } else { 3.672 + lish = -1; 3.673 + } 3.674 + lisg = startlistening(portg); 3.675 + lisc = startlistening(portc); 3.676 + 3.677 + outfd = connect_host(outname, porto); 3.678 + 3.679 + doit(infd, outfd, lish, lisg, lisc); 3.680 + 3.681 + syslog(LOG_INFO, "terminating normally\n"); 3.682 + 3.683 + fclose(stderr); 3.684 + 3.685 + closelog(); 3.686 + exit(0); 3.687 +} 3.688 + 3.689 +/* End $Id: nsplitd.c,v 2.6 1998/09/17 14:28:37 sde1000 Exp $ */