tcputils-0.6.2/ 40755 205 144 0 6517113630 12277 5ustar bellmanuserstcputils-0.6.2/ip/ 40755 205 144 0 6517113630 12707 5ustar bellmanuserstcputils-0.6.2/ip/ip_sourceroute.c100644 205 144 1011 5742250714 16214 0ustar bellmanusers/* */ #include #include "ip_misc.h" #define Export Export char * source_route(int type, char ** hostlist, int nhosts; int * result_len) { char * option; if (type != IPOPT_LSRR && type != IPOPT_SSRR) { errno = EINVAL; return NULL; } optlen = nhosts * 4 + IPOPT_MINOFF; option = malloc(optlen); if (option == NULL) return NULL; option[0] = type; option[1] = optlen; option[2] = IPOPT_MINOFF; h = &option[IPOPT_MINOFF - 1]; tcputils-0.6.2/ip/tcp_connect.c100644 205 144 1644 6166741565 15472 0ustar bellmanusers#include #include #include #include #include #include #include #include #include #include #include "ip_misc.h" #define Export /* * Open a TCP connection to REMOTE. Bind the local port to * LOCAL, if set. * Returns the file descriptor for the connection, or negative * on errors. */ Export int tcp_connect(const struct sockaddr_in * remote, const struct sockaddr_in * local) { int s; s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) return -1; if (local && bind(s, (struct sockaddr *)local, sizeof *local) < 0) { int saved_errno = errno; close(s); errno = saved_errno; return -1; } if (connect(s, (struct sockaddr *)remote, sizeof *remote) < 0) { int saved_errno = errno; close(s); errno = saved_errno; return -1; } return s; } tcputils-0.6.2/ip/addr.c100644 205 144 3103 6166714527 14073 0ustar bellmanusers#include #include #include #include #include #include #include #include #include "ip_misc.h" #define Export /* * Fill in ADDR from HOST, SERVICE and PROTOCOL. * PROTOCOL can be tcp or udp. * Supplying a null pointer for HOST means use INADDR_ANY. * Supplying a null pointer for SERVICE, means use port 0, i.e. no port. * * Returns negative on errors, zero or positive if everything ok. */ Export int get_inaddr(struct sockaddr_in * addr, const char * host, const char * service, const char * protocol) { memset(addr, 0, sizeof *addr); addr->sin_family = AF_INET; /* * Set host part of ADDR */ if (host == NULL) addr->sin_addr.s_addr = INADDR_ANY; else { addr->sin_addr.s_addr = inet_addr(host); if (addr->sin_addr.s_addr == (unsigned long)-1) { struct hostent * hp; hp = gethostbyname(host); if (hp == NULL) return -1; memcpy(&addr->sin_addr, hp->h_addr, hp->h_length); addr->sin_family = hp->h_addrtype; } } /* * Set port part of ADDR */ if (service == NULL) addr->sin_port = htons(0); else { char * end; long portno; portno = strtol(service, &end, 10); if (portno > 0 && portno <= 65535 && end != service && *end == '\0') { addr->sin_port = htons(portno); } else { struct servent * serv; serv = getservbyname(service, protocol); if (serv == NULL) return -1; addr->sin_port = serv->s_port; } } return 0; } tcputils-0.6.2/ip/tcp_open.c100644 205 144 4507 6166754350 14777 0ustar bellmanusers#include #include #include #include #include #include #include #include #include #include #include #include "ip_misc.h" #define Export /* * Open a TCP connection to port REMOTE_PORT on host REMOTE_HOST. * If LOCAL_HOST is not NULL, the local end of the connection is * bound to that address. If LOCAL_PORT is not NULL, the local * end of the connection is bound to that port. * Hosts may be given as either a numeric IP address or as a host * names. Ports may be given as either a decimal port number, or * as a symbolic service name. * * Returns the file descriptor for the connection, or negative on * errors. */ Export int tcp_open(const char *remote_host, const char *remote_port, const char *local_host, const char *local_port) { struct sockaddr_in server; struct sockaddr_in local; struct hostent * he; int s; #define ERRORRET(n) do { int e=errno;close(s);errno=e;return (n);} while (0) if (remote_host == NULL || remote_port == NULL) { errno = EINVAL; return -1; } if ((s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) return -1; if (local_host || local_port) { if (get_inaddr(&local, local_host, local_port, "tcp") < 0) ERRORRET(-1); if (bind(s, (struct sockaddr*)&local, sizeof local) < 0) ERRORRET(-1); } /* Get port */ if (get_inaddr(&server, NULL, remote_port, "tcp") < 0) ERRORRET(-1); /* Check for numerical IP address */ server.sin_addr.s_addr = inet_addr(remote_host); if (server.sin_addr.s_addr != (unsigned long)-1) { if (connect(s, (struct sockaddr*)&server, sizeof server) < 0) ERRORRET(-1); return s; } /* Not numerical address, then it should be a host name. * gethostbyname() it and try all the hosts addresses. */ if ((he = gethostbyname(remote_host)) == NULL) ERRORRET(-1); assert(he->h_addrtype == AF_INET); assert(he->h_length == sizeof server.sin_addr.s_addr); server.sin_family = he->h_addrtype; { char **a = he->h_addr_list; while (*a) { memcpy(&server.sin_addr, *a, sizeof server.sin_addr); if (connect(s, (struct sockaddr*)&server, sizeof server) >= 0) return s; a++; } } ERRORRET(-1); } tcputils-0.6.2/ip/ip_misc.h100644 205 144 1426 6166715461 14615 0ustar bellmanusers#ifndef IP_MISC_H__ALREADY_INCLUDED__ #define IP_MISC_H__ALREADY_INCLUDED__ extern int get_inaddr(struct sockaddr_in* /*addr*/, const char* /*host*/, const char* /*service*/, const char* /*protocol*/); extern int tcp_connect(const struct sockaddr_in* /*remote*/, const struct sockaddr_in* /*local*/); extern int tcp_open(const char* /*remote_host*/, const char* /*remote_port*/, const char* /*local_host*/, const char* /*local_port*/); extern int tcp_listen_2(const struct sockaddr_in* /*local*/); extern int tcp_listen(const char* /*interface*/, const char* /*port*/); extern char *source_route(int /*type*/, char** /*hostlist*/, int /*nhosts*/, int* /*result_len*/); #endif /* IP_MISC_H__ALREADY_INCLUDED__ */ tcputils-0.6.2/ip/Makefile100644 205 144 670 6167244635 14442 0ustar bellmanusersOBJECTS = addr.o tcp_connect.o tcp_open.o tcp_listen.o IPLIB = libiphelp.a CC = gcc -pedantic -Wall COPT = -g -O2 CFLAGS = ${COPT} RANLIB = ranlib all: ${IPLIB} ${IPLIB}: ${OBJECTS} ${AR} ruv $@ ${OBJECTS} ${RANLIB} $@ clean: ${RM} *.o ${IPLIB} *~ *_pure_* install: ${INSTALL} ${IPLIB} ${prefix}/lib ${INSTALL} ip_misc.h ${prefix}/include tcp_connect.o: ip_misc.h tcp_open.o: ip_misc.h tcp_listen.o: ip_misc.h addr.o: ip_misc.h tcputils-0.6.2/ip/tcp_listen.c100644 205 144 2177 6170473200 15320 0ustar bellmanusers#include #include #include #include #include #include #include #include #include #include #include "ip_misc.h" #define Export /* * Open a TCP socket listening on address LOCAL. * Returns the file descriptor for the socket, or negative * on errors. */ Export int tcp_listen_2(const struct sockaddr_in * local) { int s; struct protoent * proto; proto = getprotobyname("tcp"); if (proto == NULL) return -1; s = socket(PF_INET, SOCK_STREAM, proto->p_proto); if (s < 0) return -1; { int yes = 1; setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof yes); } if (bind(s, (struct sockaddr *)local, sizeof *local) < 0) { close(s); return -1; } if (listen(s, 256) < 0) { close(s); return -1; } return s; } Export int tcp_listen(const char * interface, const char * port) { int s; struct sockaddr_in server; if (get_inaddr(&server, interface, port, "tcp") < 0) return -1; s = tcp_listen_2(&server); return s; } tcputils-0.6.2/Makefile100644 205 144 3643 6514721356 14051 0ustar bellmanusers# Linux RedHat 5.0 has header files that generates warnings when compiling # with -pedantic, so we leave that out per default. CC = gcc -Wall #-pedantic INCLUDE-FLAGS = COPT = -g -O2 LDFLAGS = ${COPT} CFLAGS = ${COPT} ${INCLUDE-FLAGS} RANLIB = ranlib INSTALL = install -c MKDIR_P = mkdir -p # Solaris 2 needs to link with "-lsocket -lnsl". For other unices you might # need to comment out those libraries. NETLIBS = -lsocket -lnsl # Where to install things. prefix = /usr/local bindir = ${prefix}/bin mandir = ${prefix}/man man1dir = ${mandir}/man1 # ------------------------------------------------------------------ # Things below shouldn't be needed to be changed in order to compile SUBMAKE = ${MAKE} prefix="${prefix}" CC="${CC}" CFLAGS="${CFLAGS}" AR="${AR}" \ RANLIB="${RANLIB}" INSTALL="${INSTALL}" VPATH="${VPATH}" ${MFLAGS} IPLIB = ip/libiphelp.a PROGRAMS = tcpconnect tcplisten tcpbug mini-inetd getpeername MANUALS1 = tcpconnect.1 tcplisten.1 tcpbug.1 mini-inetd.1 getpeername.1 all: ${IPLIB} ${PROGRAMS} tcpconnect: tcpconnect.o relay.o ${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@ tcplisten: tcplisten.o relay.o ${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@ tcpbug: tcpbug.o relay.o ${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@ mini-inetd: mini-inetd.o ${CC} ${LDFLAGS} $^ ${IPLIB} ${NETLIBS} -o $@ getpeername: getpeername.o ${CC} ${LDFLAGS} $^ ${NETLIBS} -o $@ ${IPLIB}: cd ip; ${SUBMAKE} all clean: ${RM} ${PROGRAMS} *.o *~ core cd ip; ${SUBMAKE} clean install: install-bin install-man install-bin: ${bindir} #${PROGRAMS} ${INSTALL} ${PROGRAMS} ${bindir} install-man: ${man1dir} #${MANUALS1} ${INSTALL} ${MANUALS1} ${man1dir} install-lib: cd ip; ${SUBMAKE} install ${bindir}:; ${MKDIR_P} $@ ${man1dir}:; ${MKDIR_P} $@ ${PROGRAMS}: ${IPLIB} tcpconnect.o: ip/ip_misc.h relay.h tcplisten.o: ip/ip_misc.h relay.h tcpbug.o: ip/ip_misc.h relay.h mini-inetd.o: ip/ip_misc.h relay.o: relay.h getpeername.o: tcputils-0.6.2/relay1.c100644 205 144 3117 6224505217 13740 0ustar bellmanusers#include #include #include #include #include #include #include #define MAX(a,b) ((a) > (b) ? (a) : (b)) #define MIN(a,b) ((a) < (b) ? (a) : (b)) int relay(int fd1, int fd2, int (*callback)(char prefix, char *data, size_t nbytes)) { fd_set readset; int nfds, len; char buffer[8192]; int fd1_eof = 0; int fd2_eof = 0; while (!fd1_eof || !fd2_eof) { /* Setup file descriptor set */ FD_ZERO(&readset); if (!fd1_eof) FD_SET(fd1, &readset); if (!fd2_eof) FD_SET(fd2, &readset); nfds = select(MAX(fd1, fd2)+1, &readset, NULL, NULL, NULL); /* error? */ if (nfds < 0) { if (errno == EINTR) continue; return -1; } /* timeout? */ if (nfds == 0) continue; if (FD_ISSET(fd1, &readset)) { long unread; ioctl(fd1, FIONREAD, &unread); do { if ((len = read(fd1, buffer, sizeof buffer)) < 0) { return -1; } unread -= len; /* remote server close? */ if (len == 0) { shutdown(fd2, 1); fd1_eof = 1; } callback('>', buffer, len); write(fd2, buffer, len); } while (unread > 0); } if (FD_ISSET(fd2, &readset)) { long unread; ioctl(fd2, FIONREAD, &unread); do { if ((len = read(fd2, buffer, sizeof buffer)) < 0) { return -1; } unread -= len; /* remote client close? */ if (len == 0) { shutdown(fd1, 1); fd2_eof = 1; } callback('<', buffer, len); write(fd1, buffer, len); } while (unread > 0); } } return 0; } tcputils-0.6.2/README100644 205 144 2356 6324202501 13252 0ustar bellmanusers -*- text -*- WHAT IS THIS? This is version 0.6 of tcputils, a collection of programs to facilitate TCP programming in shell-scripts. There is also a small library which makes it somewhat easier to create TCP/IP sockets. The latest released version can be found by anonymous FTP to ftp.lysator.liu.se:pub/unix/tcputils/ (or at URL:ftp://ftp.lysator.liu.se/pub/unix/tcputils/ if you like that syntax better). I myself can be reached by email to bellman@lysator.liu.se. The programs included in this release are: mini-inetd - small TCP/IP connection dispatcher tcpbug - TCP/IP connection bugging device tcpconnect - general TCP/IP client tcplisten - general TCP/IP server getpeername - get name of connected TCP/IP peer BUILDING AND INSTALLING Read the file INSTALL for instructions. COPYRIGHT These programs are released into the public domain. You may do anything you like with them, including modifying them and selling the binaries without source for ridiculous amounts of money without saying who made them originally. However, I would be happy if you release your works with complete source for free use. WARRANTY You're kidding? You use it, you take the responsibility. Local variables: fill-column: 65 End: tcputils-0.6.2/tcplisten.c100644 205 144 6233 6514720624 14555 0ustar bellmanusers/* * tcplisten.c * Wait for a connection to a TCP/IP port, send standard input * to that connection, and print messages from that connection * on standard output. * * * This program is in the public domain. You may do anything * you like with it. * * * Author: Thomas Bellman * Lysator Computer Club * Linköping University * Sweden * email: Bellman@Lysator.LiU.Se * * * Any opinions expressed in this code are the author's PERSONAL opinions, * and does NOT, repeat NOT, represent any official standpoint of Lysator, * even if so stated. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip/ip_misc.h" #include "relay.h" extern int getopt(int, char *const*, const char *); extern int optind; char * progname = "tcplisten"; int verbose = 0; void usage(void) { fprintf(stderr, "Usage: %s [-irv] [localaddr] port\n", progname); exit(1); } void log(const char *fmt, ...) { va_list args; if (!verbose) return; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); } void fatal(char * msg) { fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); exit(1); } int main (int argc, char ** argv) { int lp; int option; int close_on_stdin_eof = 0; int close_on_remote_eof = 0; progname = argv[0]; while ((option = getopt(argc, argv, "irv")) != EOF) { switch ((char)option) { case 'i': close_on_stdin_eof = 1; break; case 'r': close_on_remote_eof = 1; break; case 'v': verbose = 1; break; default: usage(); /* NOTREACHED */ } } if (argc - optind == 1) lp = tcp_listen(NULL, argv[optind]); else if (argc - optind == 2) lp = tcp_listen(argv[optind], argv[optind+1]); else usage(); /* Some compilers might complain that 'lp' might be used uninitialized * here, but that's because they don't realize that usage() doesn't * return. */ if (lp < 0) fatal("Unable to listen to port"); { int client; struct sockaddr_in cliaddr; int cliaddrsize = sizeof cliaddr; struct relay fds[2]; int nclosed = 0; client = accept(lp, (struct sockaddr*)&cliaddr, &cliaddrsize); if (client < 0) fatal("Accept failed"); close(lp); log("[Connection from %s port %d]\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); fds[0].source = 0; fds[0].dest = client; fds[0].writeerror = 0; fds[0].readerror = 0; fds[1].source = client; fds[1].dest = 1; fds[1].writeerror = 0; fds[1].readerror = 0; signal(SIGPIPE, SIG_IGN); do { int status = relay_once(fds, 2, NULL, NULL); if (status < 0) nclosed += -status; if (close_on_stdin_eof && (fds[0].readerror || fds[1].writeerror)) { break; } if (close_on_remote_eof && (fds[1].readerror || fds[0].writeerror)) { break; } } while (nclosed < 2); log("[Connection closed]\n"); } return 0; } tcputils-0.6.2/INSTALL100644 205 144 761 6167255401 13415 0ustar bellmanusersREQUIREMENTS You need an ANSI C compiler. Gcc is a nice one that exists for most platforms. You need GNU make in order to compile. I think it's too much work to handle all other make variants with their limitations and idiosyncrasies. GNU make compiles on almost any Unix machine. If it doesn't compile on your machine, then my programs probably won't compile either anyway... TO COMPILE Edit Makefile as needed. Type "make" and wait a minute or two. TO INSTALL Type "make install". tcputils-0.6.2/tcpconnect.c100644 205 144 6255 6514720603 14711 0ustar bellmanusers/* * tcpconnect.c * Connect to a TCP/IP port, send standard input to that * connection, and print messages from that connection on * standard output. * * * This program is in the public domain. You may do anything * you like with it. * * * Author: Thomas Bellman * Lysator Computer Club * Linköping University * Sweden * email: Bellman@Lysator.LiU.Se * * * Any opinions expressed in this code are the author's PERSONAL opinions, * and does NOT, repeat NOT, represent any official standpoint of Lysator, * even if so stated. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip/ip_misc.h" #include "relay.h" extern int getopt(int, char *const*, const char *); extern int optind; extern char *optarg; char * progname = "tcpconnect"; int verbose = 0; void usage(void) { fprintf(stderr, "Usage: %s [-irv] [-l addr:port] host port\n", progname); exit(1); } void log(const char *fmt, ...) { va_list args; va_start(args, fmt); if (verbose) vfprintf(stderr, fmt, args); va_end(args); } void fatal(char * msg) { fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); exit(1); } int main (int argc, char ** argv) { int tcp; int option; int close_on_stdin_eof = 0; int close_on_remote_eof = 0; char * localaddr = NULL; char * localport = NULL; progname = argv[0]; while ((option = getopt(argc, argv, "irvl:q")) != EOF) { switch ((char)option) { case 'i': close_on_stdin_eof = 1; break; case 'r': close_on_remote_eof = 1; break; case 'l': localaddr = optarg; if ((localport = strrchr(localaddr, ':')) != NULL) { if (localaddr == localport) localaddr = NULL; *localport = '\0'; localport++; } break; case 'v': verbose = 1; break; default: usage(); /* NOTREACHED */ } } if (argc - optind != 2) usage(); { struct sockaddr_in server; int serversize = sizeof server; struct relay fds[2]; int nclosed = 0; tcp = tcp_open(argv[optind], argv[optind+1], localaddr, localport); if (tcp < 0) fatal("Can't connect to server"); if (getpeername(tcp, (struct sockaddr*)&server, &serversize) >= 0) log("[Connected to %s port %d]\n", inet_ntoa(server.sin_addr), ntohs(server.sin_port)); else log("[Connected to unknown server]\n"); fds[0].source = 0; fds[0].dest = tcp; fds[0].writeerror = 0; fds[0].readerror = 0; fds[1].source = tcp; fds[1].dest = 1; fds[1].writeerror = 0; fds[1].readerror = 0; signal(SIGPIPE, SIG_IGN); do { int status = relay_once(fds, 2, NULL, NULL); if (status < 0) nclosed += -status; if (close_on_stdin_eof && (fds[0].readerror || fds[1].writeerror)) { break; } if (close_on_remote_eof && (fds[1].readerror || fds[0].writeerror)) { break; } } while (nclosed < 2); log("[Connection closed]\n"); } return 0; } tcputils-0.6.2/tcpbug.c100644 205 144 20607 6514720561 14055 0ustar bellmanusers/* * tcpbug.c -- Accept a TCP/IP connection, and relay it to somewhere * else, while spying on the connection * * * This program is in the public domain. You may do anything * you like with it. * * * Author: Thomas Bellman * Lysator Computer Club * Linköping University * Sweden * email: Bellman@Lysator.LiU.SE * * * Any opinions expressed in this code are the author's PERSONAL opinions, * and does NOT, repeat NOT, represent any official standpoint of Lysator, * even if so stated. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip/ip_misc.h" #include "relay.h" extern int getopt(int, char *const*, const char *); extern int optind; extern char *optarg; char * progname = "tcpbug"; int quiet_mode = 0; int linewidth = -1; /* Non-zero if a bytecount should be logged */ int bug_bytecount = 0; /* Non-zero if logged data should be timestamped */ int bug_timestamp = 0; /* Non-zero if logged data should be timestamped relative to the establishing of the connection */ int bug_relative_timestamp= 0; struct bugstat { /* The prefix character */ char prefix; /* Where to send bugged data */ FILE * logfile; /* Bytes passed this way */ unsigned long nbytes; /* Function to do actual printing of bugged data */ int (*bugfun)(struct relay *, char *, size_t); /* Time when bugger() was called */ struct timeval time; /* Time when the connection was established */ struct timeval conntime; }; void log(const char *fmt, ...) { va_list args; va_start(args, fmt); if (!quiet_mode) vfprintf(stderr, fmt, args); va_end(args); } void fatal(char * msg) { fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); exit(1); } #define COLON() (things_printed++ ? putc(':', bs->logfile),++*pos : 0) int prefix(struct relay * rel, int eof, int * pos) { struct bugstat * bs = rel->userdata; int things_printed = 0; if (bug_bytecount) { char buf[sizeof bs->nbytes * CHAR_BIT]; COLON(); sprintf(buf, "%04lx", bs->nbytes); fputs(buf, bs->logfile); *pos += strlen(buf); } if (bug_timestamp) { char buf[64]; COLON(); sprintf(buf, "%ld.%06ld", bs->time.tv_sec, bs->time.tv_usec); fputs(buf, bs->logfile); *pos += strlen(buf); } if (bug_relative_timestamp) { char buf[64]; struct timeval diff; COLON(); diff.tv_sec = bs->time.tv_sec - bs->conntime.tv_sec; diff.tv_usec = bs->time.tv_usec - bs->conntime.tv_usec; if (diff.tv_usec < 0) diff.tv_usec += 1000000, diff.tv_sec -= 1; sprintf(buf, "%ld.%06ld", diff.tv_sec, diff.tv_usec); fputs(buf, bs->logfile); *pos += strlen(buf); } putc(bs->prefix, bs->logfile); if (eof) fputs("EOF\n", bs->logfile); else putc(' ', bs->logfile); return 0; } int bugger(struct relay * rel, char * data, size_t datalen) { struct bugstat * bs = rel->userdata; int pos = 0; gettimeofday(&bs->time, NULL); if (datalen == 0) { prefix(rel, -1, &pos); return 0; } bs->bugfun(rel, data, datalen); fflush(bs->logfile); return 0; } int charbugger(struct relay * rel, char * data, size_t datalen) { int pos = 0; struct bugstat *bs = rel->userdata; for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++) { register int c = (unsigned char)*data; if (pos == 0) prefix(rel, 0, &pos); if (isprint(c)) { putc(' ', bs->logfile); putc(' ', bs->logfile); putc(c, bs->logfile); } else if (c == '\n') { putc(' ', bs->logfile); putc('\\', bs->logfile); putc('n', bs->logfile); } else if (c == '\r') { putc(' ', bs->logfile); putc('\\', bs->logfile); putc('r', bs->logfile); } else if (c == '\b') { putc(' ', bs->logfile); putc('\\', bs->logfile); putc('b', bs->logfile); } else if (c == '\f') { putc(' ', bs->logfile); putc('\\', bs->logfile); putc('f', bs->logfile); } else if (c == '\t') { putc(' ', bs->logfile); putc('\\', bs->logfile); putc('t', bs->logfile); } else { putc('0' + (c>>6 & 7), bs->logfile); putc('0' + (c>>3 & 7), bs->logfile); putc('0' + (c>>0 & 7), bs->logfile); } putc(' ', bs->logfile); pos += 4; if (linewidth > 0 && pos >= linewidth) { putc('\n', bs->logfile); pos = 0; } } if (pos != 0) putc('\n', bs->logfile); return 0; } int hexbugger(struct relay * rel, char * data, size_t datalen) { int pos = 0; struct bugstat *bs = rel->userdata; static char *hexdigits = "0123456789abcdef"; for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++) { register int c = (unsigned char)*data; if (pos == 0) prefix(rel, 0, &pos); putc(hexdigits[c>>4 & 0xf], bs->logfile); putc(hexdigits[c>>0 & 0xf], bs->logfile); putc(' ', bs->logfile); pos += 3; if (linewidth > 0 && pos >= linewidth) { putc('\n', bs->logfile); pos = 0; } } if (pos != 0) putc('\n', bs->logfile); return 0; } int linebugger(struct relay * rel, char * data, size_t datalen) { int pos = 0; struct bugstat *bs = rel->userdata; for ( ; datalen > 0 ; datalen--, data++, bs->nbytes++) { register int c = (unsigned char)*data; if (pos == 0) prefix(rel, 0, &pos); putc(c, bs->logfile); pos++; if (c == '\n') { pos = 0; } #if 0 if (linewidth > 0 && pos >= linewidth) { putc('\n', bs->logfile); pos = 0; } #endif } if (pos != 0) putc('\n', bs->logfile); return 0; } void usage () { fprintf(stderr, "usage: %s [-cx] [-btT] [-w linewidth] my-port server-host server-port\n", progname); fprintf(stderr, "\t%s is a program that bugs a TCP/IP connection. It waits\n" "\tfor connections on a port that you specify, and then connects\n" "\tto a server on a machine and a port you specify. It then\n" "\tprints out everything that is sent on the connection to\n" "\tstdout.\n", progname ); exit(1); } int main (argc, argv) int argc; char **argv; { struct sockaddr_in cliaddr; int cliaddrlen = sizeof cliaddr; int listen_fd; int client_fd; int server_fd; int option; int (*bugfun)(struct relay *, char *, size_t) = NULL; progname = argv[0]; setlocale(LC_CTYPE, ""); while ((option = getopt (argc, argv, "cxw:tTb")) != EOF) { switch ((char)option) { case 'c': if (bugfun != NULL) usage(); bugfun = charbugger; if (linewidth < 0) linewidth = 72; break; case 'x': if (bugfun != NULL) usage(); bugfun = hexbugger; if (linewidth < 0) linewidth = 72; break; case 'w': linewidth = atoi(optarg); break; case 't': bug_timestamp = 1; break; case 'T': bug_relative_timestamp = 1; break; case 'b': bug_bytecount = 1; break; default: usage(); /* NOTREACHED */ } } if (argc - optind != 3) usage(); if (bugfun == NULL) bugfun = linebugger; listen_fd = tcp_listen(NULL, argv[optind]); if (listen_fd < 0) fatal("can't listen to port"); client_fd = accept(listen_fd, (struct sockaddr *)&cliaddr, &cliaddrlen); if (client_fd < 0) fatal("accept failed"); log("[Connection from %s port %d]\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); close(listen_fd); server_fd = tcp_open(argv[optind+1], argv[optind+2], NULL, NULL); if (server_fd < 0) fatal("can't connect to server"); { struct relay fds[2]; struct bugstat buggers[2]; struct timeval now; gettimeofday(&now, NULL); signal(SIGPIPE, SIG_IGN); fds[0].source = client_fd; fds[0].dest = server_fd; fds[0].readerror = 0; fds[0].writeerror = 0; fds[0].userdata = &buggers[0]; buggers[0].nbytes = 0; buggers[0].prefix = '>'; buggers[0].logfile = stdout; buggers[0].bugfun = bugfun; buggers[0].conntime = now; fds[1].source = server_fd; fds[1].dest = client_fd; fds[1].readerror = 0; fds[1].writeerror = 0; fds[1].userdata = &buggers[1]; buggers[1].nbytes = 0; buggers[1].prefix = '<'; buggers[1].logfile = stdout; buggers[1].bugfun = bugfun; buggers[1].conntime = now; relay_all(fds, 2, bugger); } return 0; } tcputils-0.6.2/mini-inetd.c100644 205 144 5413 6517113544 14604 0ustar bellmanusers#include #include #include #include #include #include #include #include #include #include #include #include #include #include "ip/ip_misc.h" extern char ** environ; extern int getopt(int, char *const*, const char *); extern int optind; extern char * optarg; char * progname = "mini-inetd"; int debug = 0; int max_connections = 0; static void usage() { fprintf(stderr, "Usage: %s [-d] [-m max] port program [argv0 argv1 ...]\n", progname); exit(1); } static void vfatal(const char *fmt, va_list args) { fputs(progname, stderr); fputs(": ", stderr); vfprintf(stderr, fmt, args); putc('\n', stderr); exit(1); } static void fatal(const char *fmt, ...) { va_list args; va_start(args, fmt); vfatal(fmt, args); va_end(args); } static void reap_children(int signo) { pid_t child; int status; char buf[64 + sizeof(long) * CHAR_BIT]; while ((child = waitpid(-1, &status, WNOHANG)) > (pid_t)0) { if (debug) { sprintf(buf, "Child %ld died\n", (long)child); write(2, buf, strlen(buf)); } } signal(signo, &reap_children); } int main(int argc, char **argv) { int sd; pid_t child; int option; char *host; char *port; while ((option = getopt (argc, argv, "dm:")) != EOF) { switch ((char)option) { case 'd': debug++; break; case 'm': max_connections = atoi(optarg); break; default: usage(); /* NOTREACHED */ } } if (argc - optind < 2) usage(); port = strrchr(argv[optind], ':'); if (port != NULL) { *(port++) = '\0'; host = argv[optind]; } else { port = argv[optind]; host = NULL; } if ((sd = tcp_listen(host, port)) < 0) fatal("Can't listen to port %s: %s", argv[optind], strerror(errno)); /* Reap children */ #if defined(SIGCHLD) signal(SIGCHLD, &reap_children); #elif defined(SIGCLD) signal(SIGCLD, &reap_children); #endif while (1) { struct sockaddr_in them; int len = sizeof them; int ns = accept(sd, (struct sockaddr*)&them, &len); if (ns < 0) { if (errno == EINTR) continue; fatal("Accept failed: %s", strerror(errno)); } switch (child = fork()) { case -1: perror("Can't fork"); break; case 0: /* Child */ close(sd); dup2(ns, 0); dup2(ns, 1); execve(argv[optind+1], argv+optind+2, environ); fatal("Can't start %s: %s", argv[optind+1], strerror(errno)); default: /* Parent */ if (debug) fprintf(stderr, "Forked child %ld\n", (long)child); close(ns); break; } if (max_connections > 0 && --max_connections <= 0) break; } return 0; } tcputils-0.6.2/relay.c100644 205 144 10671 6514720342 13702 0ustar bellmanusers#include #include #include #include #include #include #if defined(__hpux__) || defined(__linux__) # include #else # include #endif #include #include "relay.h" #define Export #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) /* * Estimate how many bytes are available for reading on a file descriptor. */ static long available_bytes(int fd) { long nbytes; struct stat sb; off_t pos; /* * Some Unices don't support the FIONREAD ioctl on regular files. * They don't even return an error, but says there are zero bytes * to be read. We then try to fstat() the file descriptor to see * how big the file is, and try to determine at what offset the * file pointer is at now. That doesn't work always either... */ if (ioctl(fd, FIONREAD, &nbytes) < 0 || nbytes == 0) { if (fstat(fd, &sb) < 0) return -1; errno = 0; pos = lseek(fd, 0, SEEK_CUR); if ((pos < 0 && errno != 0) || !S_ISREG(sb.st_mode)) pos = 0; nbytes = sb.st_size - pos; } return nbytes; } /* * Wait for data to arrive on any of the source file descriptors in * RELAYS, read all available data, and write to respective dest * file descriptors. TIMEOUT is the maximum time to wait, or a nil * pointer to never time out. For each read() done, the function * CALLBACK is called. Note that CALLBACK may be called more than * once for each file descriptor if much data is available. * NRELAYS is the number of elements in RELAYS. * * If the 'readerror' field is non-zero for a relay, no read will be * attempted from the source file descriptor of that relay. * If the 'writerror' field is non-zero for a relay, no write will be * attempted to the dest file descriptor of that relay, but the source * descriptor will still be drained from any available data. * * If end-of-file is reached on the source of a relay, the corresponding * destination will be shutdown() for writing, thus causing the other * end to see a end-of-file. * If a write error occurs on the destination of a relay, the source * of that relay will be shutdown() for reading, causing the other end * to get errors when trying to write more data to us. * Note that the SIGPIPE signal should be ignored, or possibly caught, * by the caller, or the process will die when a receiver closes its * end for receiving. * * Returns the number of file descriptor read from, or negative on error. */ Export int relay_once(struct relay * relays, int nrelays, struct timeval * timeout, int (*callback)(struct relay*, char*, size_t) ) { int maxfd; fd_set readset; int i; int nfds; int nerrors = 0; FD_ZERO(&readset); maxfd = 0; for (i = nrelays - 1 ; i >= 0 ; i--) { if (!relays[i].readerror) { FD_SET(relays[i].source, &readset); if (relays[i].source > maxfd) maxfd = relays[i].source; } } nfds = select(maxfd+1, &readset, (fd_set*)NULL, (fd_set*)NULL, timeout); if (nfds <= 0) { if (errno != EINTR) return nfds; else return 0; } for (i = nrelays - 1 ; i >= 0 ; i--) { if (FD_ISSET(relays[i].source, &readset)) { long unread = available_bytes(relays[i].source); do { char buffer[8192]; int bytes_read = read(relays[i].source, buffer, sizeof buffer); if (bytes_read < 0) { relays[i].readerror = errno; nerrors++; break; } unread -= bytes_read; if (bytes_read == 0) { relays[i].readerror = -1; shutdown(relays[i].dest, 1); nerrors++; } if (callback) (*callback)(&relays[i], buffer, bytes_read); if (!relays[i].writeerror && bytes_read > 0) { int written = write(relays[i].dest, buffer, bytes_read); if (written < 0) { relays[i].writeerror = errno; shutdown(relays[i].source, 0); nerrors++; break; } } } while (unread > 0); } } return nerrors ? -nerrors : nfds; } /* * Call relay_once() until end-of-file has been reached on all sources. * No time limit. */ Export int relay_all(struct relay * relaylist, int nrelays, int (*callback)(struct relay*, char*, size_t)) { int nclosed = 0; do { int status = relay_once(relaylist, nrelays, NULL, callback); if (status < 0) nclosed += -status; } while (nclosed < nrelays); return 0; } tcputils-0.6.2/fionread.c100644 205 144 362 6224431657 14317 0ustar bellmanusers#include #include int main(int argc, char **argv) { long unread = 0; int status = 0; status = ioctl(0, FIONREAD, &unread); printf("Status: %d Unread: %ld\n", status, unread); return 0; } tcputils-0.6.2/relay.h100644 205 144 1070 6227202134 13653 0ustar bellmanusersstruct relay { /* IN: file descriptor to read from */ int source; /* IN: file descriptor to read to */ int dest; /* IN+OUT: errno for failed read. -1 if EOF reached. */ int readerror; /* IN+OUT: errno for failed write. EPIPE if receiver is dead. */ int writeerror; /* IN: for private use by the callback function */ void * userdata; }; extern int relay_once(struct relay *, int, struct timeval *, int (*)(struct relay*, char*, size_t)); extern int relay_all(struct relay *, int, int (*)(struct relay*, char*, size_t)); tcputils-0.6.2/fstat.c100644 205 144 1417 6224434225 13665 0ustar bellmanusers#include #include #include #include int main(int argc, char **argv) { struct stat f; int status; status = fstat(0, &f); printf("Status: %d errno: %d\n", status, errno); printf("st_mode: %o\n", f.st_mode); printf("st_ino: %d\n", f.st_ino); printf("st_dev: %d\n", f.st_dev); printf("st_rdev: %d\n", f.st_rdev); printf("st_nlink: %d\n", f.st_nlink); printf("st_uid: %d\n", f.st_uid); printf("st_gid: %d\n", f.st_gid); printf("st_size: %d\n", f.st_size); printf("st_atime: %d\n", f.st_atime); printf("st_mtime: %d\n", f.st_mtime); printf("st_ctime: %d\n", f.st_ctime); printf("st_blksize: %d\n", f.st_blksize); printf("st_blocks: %d\n", f.st_blocks); return 0; } tcputils-0.6.2/version.h100644 205 144 51 6227174764 14203 0ustar bellmanuserschar *tcputils_version = "tcputils 0.6"; tcputils-0.6.2/tcpconnect.1100644 205 144 2371 6324156023 14620 0ustar bellmanusers.TH TCPCONNECT 1 "1997 April 13" .SH NAME tcpconnect \- general TCP/IP client .SH SYNOPSIS .B tcpconnect .RB [ -irv ] \fR[\fB\-l \fIlocaladdr\fR] .I host .I port .SH DESCRIPTION .B tcpconnect creates a TCP/IP connection to a server running on the machine .IR host , listening to port .IR port . It then reads standard input and sends to the remote server, and data received from the server is printed to standard output. When end-of-file is reached on both standard input and the TCP/IP connection, .B tcpconnect terminates. .SH OPTIONS .TP .B \-i Terminate at end-of-file on standard input; don't wait for the server to close the connection. .TP .B \-r Terminate when the remote server closes the connection; don't wait for end-of-file on standard input. .TP .B \-v Verbose mode. Prints a message to standard error when the connection has been established. .TP .B \-l \fIaddr\fB:\fIport Bind the local end-point of the connection to IP address .IR addr , TCP port .IR port . Either the IP address or the port, but not both, may be left out, meaning that the operating system gets to choose that part by itself. .SH SEE ALSO .PD .BR tcplisten (1), .BR telnet (1), .BR tcpbug (1). .SH BUGS The names of the options are not yet finalized, and may change at a future release. tcputils-0.6.2/tcplisten.1100644 205 144 2152 6324156001 14456 0ustar bellmanusers.TH TCPCONNECT 1 "1997 April 13" .SH NAME tcplisten \- general TCP/IP server .SH SYNOPSIS .B tcplisten .RB [ -irv ] .RI [ localaddr ] .I port .SH DESCRIPTION .B tcplisten waits for a TCP/IP connection on .IR port . If a .I localaddr parameter is given, .B tcplisten will bind to that IP address. Otherwise .B tcplisten will accept connections to any of the local machines IP addresses. Data received from the client is printed on standard output, and data read from standard input is sent to the client. When end-of-file is reached on both standard input and the TCP/IP connection, .B tcplisten terminates. .SH OPTIONS .TP .B \-i Terminate at end-of-file on standard input; don't wait for the client to close the connection. .TP .B \-r Terminate when the remote client closes the connection; don't wait for end-of-file on standard input. .TP .B \-v Verbose mode. Prints a message to standard error about the origins (host and port) of the client. .SH SEE ALSO .PD .BR tcpconnect (1), .BR telnet (1), .BR mini-inetd (1), .BR tcpbug (1). .SH BUGS The names of the options are not yet finalized, and may change at a future release. tcputils-0.6.2/getpeername.c100644 205 144 4563 6517062555 15055 0ustar bellmanusers#include #include #include #include #include #include #include #include #include extern int getopt(int, char *const*, const char *); extern int optind; extern char *optarg; char * progname = "getpeername"; int numeric_addresses = 0; char * protocol = NULL; int sockno = 0; void usage(void) { fprintf(stderr, "Usage: %s [-n] [-p protocol]\n", progname); exit(1); } void fatal(char * msg) { fprintf(stderr, "%s: %s: %s\n", progname, msg, strerror(errno)); exit(1); } int main(int argc, char **argv) { int option; struct sockaddr_in peer; int peersize = sizeof peer; char * hostname; char * portname; char servbuf[64]; progname = argv[0]; while ((option = getopt(argc, argv, "np:")) != EOF) { switch ((char)option) { case 'n': numeric_addresses = 1; break; case 'p': protocol = optarg; break; default: usage(); /* NOTREACHED */ } } if (argc - optind > 0) usage(); if (getpeername(sockno, (struct sockaddr*)&peer, &peersize) < 0) fatal("can't get peer name"); if (peer.sin_family != AF_INET) fatal("socket is not an IP socket"); /* Find the type of the socket. Assumes that an INET stream socket * is TCP and an INET datagram socket is UDP. Can't handle AF_UNIX * or any other adress families. */ if (protocol == NULL) { int socktype; int socktypelen = sizeof socktype; if (getsockopt(sockno, SOL_SOCKET, SO_TYPE, (char*)&socktype, &socktypelen) < 0) fatal("can't get socket type"); switch (socktype) { case SOCK_STREAM: protocol = "tcp"; break; case SOCK_DGRAM: protocol = "udp"; break; default: fatal("unknown socket type"); /* NOTREACHED */ } } hostname = inet_ntoa(peer.sin_addr); sprintf(servbuf, "%u", ntohs(peer.sin_port)); portname = servbuf; if (!numeric_addresses) { struct hostent *host; struct servent *service; host = gethostbyaddr((char*)&peer.sin_addr.s_addr, sizeof peer.sin_addr.s_addr, AF_INET); if (host != NULL) hostname = host->h_name; service = getservbyport(peer.sin_port, protocol); if (service != NULL) portname = service->s_name; } printf("%s %s\n", hostname, portname); return 0; } tcputils-0.6.2/tcpbug.1100644 205 144 3373 6324213672 13753 0ustar bellmanusers.TH TCPBUG 1 "1997 April 13" .SH NAME tcpbug \- TCP/IP connection bugging device .SH SYNOPSIS .B tcpbug .RB [ -cx ] .RB [ -btT ] .I local-port .I remote-host .I remote-port .SH DESCRIPTION .B tcpbug forwards a TCP/IP connection to port \fIlocal-port\fP on the local machine to the port \fIremote-port\fP on \fIremote-host\fP while spying on the connection and writing all data passing through to standard output. All data coming from the client is printed with a greater than sign (\fB>\fP) first on each line, and all data coming from the server is printed with a less than sign (\fB<\fP) first on each line. Any byte offsets and time-stamps are printed before the greater than or less than sign, and are separated from each other by a colon (\fB:\fP). .SH OPTIONS .TP .B \-b Print the offset of the first byte in the stream for each line. .TP .B \-c Display bytes as individual characters. Printable characters are displayed directly, some control characters appear as C-language escapes .RB ( \en ", " \er ", " \et " et.c)," while others appear as 3-digit octal numbers. This should be similar to the -c switch of .BR od (1). .TP .B \-t Print the time at which the data was received for each line. The time is the number of seconds and microseconds, separated by a decimal point .RB ( . ), since 00:00 UTC, January 1, 1970, as reported by gettimeofday(). .TP .B \-T Print the time at which the data was received for each line. The time is the number of seconds and microseconds, separated by a decimal point .RB ( . ), since the connections were established. .TP .B \-x Display each byte as a two digit hexadecimal number. .SH SEE ALSO .PD .BR tcpconnect (1), .BR tcplisten (1), .BR od (1). .SH BUGS The names of the options are not yet finalized, and may change at a future release. tcputils-0.6.2/getpeername.1100644 205 144 1434 6324215416 14755 0ustar bellmanusers.TH GETPEERNAME 1 "1997 April 13" .SH NAME getpeername \- get name of connected TCP/IP peer .SH SYNOPSIS .B getpeername .RB [ -n ] \fR[\fB\-p \fIprotocol\fR] .SH DESCRIPTION .B getpeername prints the IP address and service name (port number) of the remote peer connected to standard input. The IP address and the service name are printed on the same line, separated by one space. .SH OPTIONS .TP .B \-n Don't translate IP addresses and port numbers to names. .TP .B \-p \fIprotocol\fP Force getpeername to use \fIprotocol\fP as the protocol when translating port numbers to service names. \fIProtocol\fP can be \fBtcp\fP and \fBudp\fP. Normally, getpeername automatically determines what type of socket it is connected to. .SH SEE ALSO .PD .BR getpeername (3). .SH BUGS Only works on IP sockets. tcputils-0.6.2/mini-inetd.1100644 205 144 1603 6324175337 14523 0ustar bellmanusers.TH MINI-INETD 1 "1997 April 13" .SH NAME mini-inetd \- small TCP/IP connection dispatcher .SH SYNOPSIS .B mini-inetd .RB [ -d ] \fR[\fB-m \fImaxconnections\fR] .I \fR[\fPlocaladdr\fB:\fP\fR]\fPport .I program [\fIargv0 argv1\fR ...] .SH DESCRIPTION .B mini-inetd listens for TCP/IP connections on \fIport\fP. For each connection, \fIprogram\fP is started with standard input and standard output connected to the socket. If \fIlocaladdr\fP is given, mini-inetd only listens for connections on the interface specified by that hostname or IP address, otherwise, it listens to all IP interfaces on the machine. .SH OPTIONS .TP .B \-d Debug... .TP .B \-m \fImaxconnections\fP Exit after \fImaxconnections\fP connections has been handled. .SH SEE ALSO .PD .BR tcpconnect (1), .BR tcplisten (1), .BR inetd (1m). .SH BUGS The names of the options are not yet finalized, and may change at a future release.