From: neural@cs.tu-berlin.de (Simon Ney) Newsgroups: alt.sources Subject: TAP - BIG BROTHERS STREAMS TAP DRIVER (1.24) Date: 22 Mar 92 21:25:18 GMT Followup-To: alt.sources Organization: Technical University of Berlin, Germany this version now runs on sun3 and sun4 now. for more details see the README below ---- Cut Here and unpack ---- #!/bin/sh # This is a shell archive (shar 3.32) # made 03/22/1992 20:51 UTC by root@bbisun # Source directory /usr/local/src/DEVICE-DRIVER/tap/RELEASE # # existing files WILL be overwritten # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 15352 -r--r--r-- README # 2484 -r--r--r-- INSTALL # 1672 -r--r--r-- Makefile # 1529 -r--r--r-- load # 271 -r--r--r-- unload # 8013 -r--r--r-- tap.c # 268 -r--r--r-- tap.h # 2659 -r--r--r-- tapmon.c # 1387 -r--r--r-- streams.c # if touch 2>&1 | fgrep 'amc' > /dev/null then TOUCH=touch else TOUCH=true fi # ============= README ============== echo "x - extracting README (Text)" sed 's/^X//' << 'SHAR_EOF' > README && X# @(#)README 1.24 3/22/92 X# X############################################################################ X# This is the STREAMS tap module/driver pseudo-device. aka WATER-WORKS X############################################################################ X# X# runs on: X# sun3/50 4.1.1 X# sun4/75 4.1.2 X# X XCOPYRIGHT: X - you want COPYRIGHT ? i will give you COPYRIGHT. X Copyright (c) 1992 Simon Ney -- All Rights Reserved X X X --------------- X X XDESCRIPTION: X - the device is a monitor/manipulator for other STREAMS-devices X such as standard UNIX control-terminals. X X - this driver is a kernel-loadable-module. (==>no reboot required) X X - it is a combination of a STREAMS-module and a STREAMS-driver. X X tap - is the name of the pushable/poppable STREAMS-modules. X tapc* - are the names of the STREAMS-driver nodes (special X files).. X X - the tap-modules must first manually pushed/popped on each stream X to be monitored or manipulated, independ if the tapc-driver is X open or not. see also ioctl(fd,I_PUSH|I_POP,"tap"). X X - the first module pushed become the id 0, the second 1, and so on... X if any of these modules are popped the next pushed will become X the old id of the previous popped module. the module ids are X always unique, and are assigned first fit. X the maximal number of tap-modules pushed is NTAP (see tap.h). X X - a pushed-tap-module act as NULL-streams-MODULE (pass data from below X to above and data from above to below) unless it is connected with X the tapc-driver. X X - now if a minor device of the tapc-driver is opened the minor X device-number is used to check if such tap-module is pushed X (minor number = tap-id). if no such module id is present a X ENETUNREACH (Network is unreachable) error is returned by open(). X if the module id (minor device number) can be found, a connection X to the pushed-tap-module is established. X X - all minor-device-nodes can only open by one user at a time, X the second open() on the same minor device returns a EBUSY (Device X busy) error. X X - if the open() has the O_NDELAY flag set a TAP_REVERSE flag X is internal set in the driver. the TAP_REVERSE flag can only X set by the super-user, a non-superuser open() returns a EACCES X (Permission denied) error. X X - now data can be received/send from/to the pushed-tap-module X with read() and write(). X X - if the TAP_REVERSE flag is not set, data received by the tap-module X from the above modules/streamshead (upper-stream) is duplicated X and send to the read-side of the tapc-driver, and can be read by X the user process that opened the tapc-driver. X data written with write() by the process that opened the tapc-driver X are send to modules/streamshead above the tap-module (upper-stream). X X - if the TAP_REVERSE flag is set, data received by the tap-module X from the module/driver below the tap-module (lower-stream) is X duplicated and send to the read-side of the tapc-driver, and can X be read by the user process that opened the tapc-driver. X data written with write() by the process that opened the tapc-driver X are send to the modules/driver below the tap-module (lower-stream). X X - if the tapc-driver is closed the messages are not dupclicated as X long as the tapc-driver is re-open. (the tap-modules remains X pushed) X X - if data is written by the tapc-driver and the connected module X was popped a ENETCONNRESET (Connection reset by peer) error is X return to the write(). X X - if the stream that has the tap-module pushed is closed, all modules X on this stream are popped by the system. but there is a configuration X option in sunos to autopush any modules on open() (that's different X in a SYSV environment). X X X --------------- X X XFIGURES: X (USER PROCESS) (BIG BROTHER) X (csh,vi) (tapmon) (tapmon -r) (tip/cu/uucico) X /dev/ttya /dev/tapc0 /dev/tapc1 /dev/cua1 X-------------------------------------------------------------------------------- X |ttya HEAD | |tapc HEAD| |tapc HEAD| |cua1 HEAD | X +----------+ +---------+ +---------+ +----------+ X | ^ | ^ | ^ | ^ X | | | | | | | | X | | ........... ........... | | X | | . MORE . . MORE . | | X | | . MODULES . . MODULES . | | X | | ........... ........... | | X | | | | | | | | X v | v | v | | | X ............ +---------+ +---------+ ............ X . MORE (2). |TAPC 0 | |TAPC 1 | . MORE (2) . X . MODULES . |DRIVER | |DRIVER(1)| . MODULES . X ............ +---------+ +---------+ ............ X (3)| ^(4) | ^ | ^ | | UPPER X v | | | | | v | STREAMS X +----------+ | | | | +----------+ X | \ \ | | | | | | TAP 1 | X | \ \--|<---------/ | | \--------|\ MODULE | X | TAP 0\---|------------/ \--------->| \ PUSHED| X | MODULE | |\ \REVERSE| X | PUSHED | | \ \ OPEN | X | | <--- NORMAL REVERSE---> | \ \ | X +----------+ +----------+ X | ^ (4)| ^(3) LOWER X v | v | STREAMS X ............ ............ X . MORE (2). . MORE . X . MODULES . . MODULES . X ............ ............ X | ^ | ^ X v | v | X +----------+ +----------+ X | zs DRIVER| | zs DRIVER| X-------------------------------------------------------------------------------- X physical STREAMS device physical STREAMS device X (terminal) (modem) X (intruder) (other systems) X X ---------- X (1) - opened by O_NDELAY from root X (2) - e.g. ttcompat,ldterm,kb,ms, X slip,ax25,pf,nbuf X (3) - duplicated streams X (4) - multiplexed streams X X XNOTE: the ,,physical STREAMS device'' above shown can be any streams device X e.g.: /dev/{tty*,console,nit,tcp,loop,mux,mti,kbd,mouse,*CLONE*} X (nit and tcp is a clone device !) X slip cant monitored because itself pops all modules pushed. X the only way is to modify sliplogin.c to push the tap module below X the slip module. X X X --------------- X X X XINSTALLATION: X the current version has been tested under sunos 4.1.1 on a sun3/50 X and sunos 4.1.2 on a sun4/75. but i hope the version will run on any X sun with the loadable-driver /dev/vd,otherwise read the INSTALL file X and your STREAMS programming manual (the load of the pushable X streams-module is done by hand on suns). if the modload(8) X fails or the use of the driver crashes the kernel let me know ... X X to make the kernel-loadable module and automatic load into the kernel X type (as root); X X # make X X the tapmon(1)+streams(1) user-commands are created.(the streams(1) X command can be used to push/pop other non-tap streams modules,the X tapmon(1) is a TAP-driver application). X a possible old tap-module is automatically unloaded if a new is loaded X (after multiple make commands). the device nodes (/dev/tapc*) are X created as expected. X X X X --------------- X X X XSOME EXAMPLES: X now login from ttya before continue (or pick a already opened X pseudo-tty from the window-system (NOT the one you will enter X the following commands)) X X # streams -u tap < /dev/ttya X # tapmon 0 X X this push a tap-module on the already open /dev/ttya serial-tty and X then start the monitor/manipulator. all data send to /dev/ttya are X now duplicated to your standard output,and all data send by you are X send as input to the process on ttya, thats the same as you are sit X in front of ttya. X type CTRL-_ to leave the tapmon. X NOTE: after leaving tapmon the tap-streams-modules remains pushed. X X here an example output from ,,pstat -S'' while one tapmon is running: X X LOC WRQ VNODE DEVICE PGRP SIGIO FLAGS X f05461e f05583c f0cdb94 59, 0 0 0 R X Write side: X NAME COUNT FLG MINPS MAXPS HIWAT LOWAT X strwhead 0 0 0 0 0 X tapc 0 R 0 INF 0 0 X Read side: X tapc 0 R 0 INF 0 0 X strrhead 0 R 0 INF 5120 1024 X X X LOC WRQ VNODE DEVICE PGRP SIGIO FLAGS X f0543e0 f0550ec f0cc9f4 12, 1 905 0 X Write side: X NAME COUNT FLG MINPS MAXPS HIWAT LOWAT X strwhead 0 0 0 0 0 X tap 0 R 0 INF 0 0 X ttcompat 0 R 0 INF 300 200 X ldterm 0 R 0 INF 1 0 X zs 0 R 0 INF 2048 128 X Read side: X zs 0 R 0 INF 2048 128 X ldterm 0 R 0 128 500 200 X ttcompat 0 R 0 INF 2048 128 X tap 0 R 0 INF 0 0 X strrhead 0 0 INF 300 200 X X X the kernel-loadable-module can only unloaded by ./unload or by X modunload(1) if all tap-modules are popped and the /dev/tapc* devices X are closed (if you are not sure look in ,,pstat -S'' for the X string "tap" ). X X # streams -o tap < /dev/ttya X # ./unload X X this pops the previous pushed module and unloads the X kernel-loadable-module from the kernel... X X NOTE: always use ./unload instead of modunload(8) because the Makefile X keep track of the loaded kernel-modules ! X X another example is (if you not already done the ./unload operation X above,otherwise you must reload the tapc/tap driver with another X ,,make''): X X # streams -o ttcompat -o ldterm \ X -u tap -u ldterm -u ttcompat < /dev/ttya X # tapmon 0 X X now you can monitor direct above the physical device and below X the ldterm module and can see the line-editing functions of X the ldterm and ttcompat modules. X also signals send by you, such as CTRL-C are processes by the X ldterm and ttcompat modules and send as signal to the process X as expected (in the former example not, a CTRL-C was send as X input byte 0x03 to the user-process) X X here how to undo the last modules transaction: X X # streams -o ttcompat -o ldterm -o tap -u ldterm \ X -u ttcompat < /dev/ttya X X NOTE: the order of ther streams(1) command is important (stack order). X X X X --------------- X X XKERNEL CONFIG: X if you want to link the tapc/tap device-driver permanently to /vmunix X be sure not to define TAPVD (see Makefile) and to ignore tap.h X (see tap.h). follow the steps in the ,,INSTALL'' file. X X X --------------- X X XKNOWN BUGS: X - CLONE open are currently disabled because it may crash the kernel, X after 7 modules are pushed and 7 tapmons (using clone open) started X in backgroup then close the stream that has the 7 modules pushed, X and then reconnected to the tapmons with csh ,fg'' command, the 7th X ,,fg'' crash the sun3sunos4.1.1 kernel with the following message: X **** X ,,assertion failed: vp->v_stream, file: ../../os/str_io.c, line 3823'' X ,,panic: assertion failed'' X **** X the kernel-backtrace shows than it was called from some kernel X select(), thats the first function tapmon calls after the CLONE open. X X - if the BUG is fixed CLONE opens connects to the first unconnected X module, and not the last pushed module! X X X --------------- X X XSECURITY NOTES: X - the paranoid sysadmin must decide what permission he want to give to X the /dev/tapc* devices (e.g. chmod 600 /dev/tapc*). X the TAP_REVERSE mode can only be used by the super-user because X it can be used to read clear text passwords during login-time and X to get control of external devices such as modems and communication X devices. X X - a typical LUSER can start ,,pstat -S'' to see if BIG BROTHER is X watching... X X X --------------- X X XCOMMENTS: X - you can use TAP for education proposes if you push multiple X tap-modules on a single stream or you can create BIG BROTHER trees, X and make a UNIX alliance so that multiple users use the same X shell,editor.... and can correct each other....or to help UNIX X beginners....isnt it a some kind of human-neural-nets ? X X - the only problem is the possible wrong terminal-emulation *sigh*. X but there is a universal-terminal-emulation under X, and the screen X command from Oliver Laumann. X X - a MAN page is included in the next release. X X - i hope my english is funny... X X UNIX - is a registed bell of AT&T trademark laboratories. X X-- XSimon Ney -- neural@cs.tu-berlin.de -- simon@bbisun.uu.sub.org SHAR_EOF $TOUCH -am 0322215092 README && chmod 0444 README || echo "restore of README failed" set `wc -c README`;Wc_c=$1 if test "$Wc_c" != "15352"; then echo original size 15352, current size $Wc_c fi # ============= INSTALL ============== echo "x - extracting INSTALL (Text)" sed 's/^X//' << 'SHAR_EOF' > INSTALL && X# X# @(#)INSTALL 1.24 3/22/92 X# X XSTEPS TO CONFIGURE YOUR KERNEL FOR TAPC/TAP: X X i recommend that you first try the kernel-loadable X version of the driver by just type ,,make'' (see README) X and make later the steps below... X X------------------------------------------------------------------------- X1. Add: X X sundev/tap.c optional tap device-driver X X to /usr/sys/`arch -k`/conf/files X X------------------------------------------------------------------------- X2. Copy tap.c to /usr/sys/sundev/tap.c X X------------------------------------------------------------------------- X3. Add X X ... X #include "tap.h" X #if NTAP > 0 X extern struct streamtab tapcinfo; X #define tapctab &tapcinfo X #else X #define tapctab 0 X #endif X ... (at the end of the cdevsw[]) X { X nodev, nodev, nodev, nodev, /*104*/ X nodev, nulldev, nodev, 0, X tapctab, 0, X }, X ... X X to /usr/sys/sun/conf.c X (write down the major number (e.g. 104)) X X------------------------------------------------------------------------- X4. Add X X ... X #include "tap.h" X ... X #if NTAP > 0 X extern struct streamtab tapinfo; X #endif X ... X #if NTAP > 0 X { "tap", &tapinfo }, X #endif X ... X X to /usr/sys/sun/str_conf.c X X------------------------------------------------------------------------- X5. Add X X pseudo-device tap8 # STREAMS tapc/tap driver/module X X to your /usr/sys/`arch -k`/conf/CONFIG file. X (8 = maximal 8 modules and devices for the system,max 256) X------------------------------------------------------------------------- X6. Configure your kernel and install and boot it X X # cd /usr/sys/`arch -k`/conf X # config CONFIG X # cd ../CONFIG X # make X # cp /vmunix /vmunix.old X # cp vmunix / X # ls -l /dev/tapc* X # rm -f /dev/tapc* X # mknod /dev/tapc0 c 104 0 # major 104 is the number from step 3. above X # mknod /dev/tapc1 c 104 1 X . X . X . X # mknod /dev/tapc7 c 104 7 X # fastboot X X------------------------------------------------------------------------- X7. In your TAP-SOURCE directory X X # make install # to install streams+tapmon in /usr/local/etc X------------------------------------------------------------------------- X SHAR_EOF $TOUCH -am 0322215092 INSTALL && chmod 0444 INSTALL || echo "restore of INSTALL failed" set `wc -c INSTALL`;Wc_c=$1 if test "$Wc_c" != "2484"; then echo original size 2484, current size $Wc_c fi # ============= Makefile ============== echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# @(#)Makefile 1.24 3/22/92 X############################################################################### X# X# --- kernel loadable-module tap streams-module/driver pseudo-device --- X# X# SEE ALSO X# modload(8) X# modunload(8) X# modstat(8) X# vd(4) X# X# TAPDEBUG -to show the tap structure every time a modstat(8) is started X# X# TAPVD -indicates kernel-loadable version X# X# TAPVDDUAL -must be defined only if a driver is already linked to /vmunix X# and a additional loadable-driver should be loaded w/o confusing X# duplicate module-names ( "tapc"/"tap" strings are changed X# to "tapcvd"/"tapvd" ) X# X############################################################################### X# X# TAPCLONE -WARNING define ONLY after you have read the BUGS section X# in the README file X# X############################################################################### X XCFLAGS= -O -DKERNEL -D`arch -k` -DTAPVD # -DTAPDEBUG ### -DTAPCLONE XINSDIR= /usr/local/etc XFILES= README INSTALL Makefile load unload tap.c tap.h tapmon.c streams.c XMIDF= /tmp/MODULE_ID # removed by reboot(8) and ./unload X Xall: EXECS $(FILES) streams tapmon module X Xmodule: tap.o X if( test -f $(MIDF) ) then \ X ./unload ; \ X fi X modload -exec ./load tap.o X modstat X Xtap.c: tap.h X XEXECS: load unload X chmod a+x load unload X touch $@ # WELCOME TO WATER-WORKS ... X Xedit: X sccs edit $(FILES) X chmod a+x load unload X Xdelta: X sccs delta $(FILES) X Xinstall:streams tapmon X install -s -m 755 -o bin -g bin streams $(INSDIR) X install -s -m 755 -o bin -g bin tapmon $(INSDIR) X Xclean: X rm -f EXECS tap.o tap tapmon streams X Xshar: $(FILES) X shar -c $(FILES) > tap1.24.shar X SHAR_EOF $TOUCH -am 0322215192 Makefile && chmod 0444 Makefile || echo "restore of Makefile failed" set `wc -c Makefile`;Wc_c=$1 if test "$Wc_c" != "1672"; then echo original size 1672, current size $Wc_c fi # ============= load ============== echo "x - extracting load (Text)" sed 's/^X//' << 'SHAR_EOF' > load && X#! /bin/sh X# @(#)load 1.24 3/22/92 X XPATH=/usr/ucb:/bin:/usr/bin:/usr/etc ; export PATH X X# --- change here --- XCDEVICE="/dev/tapc" XCMINORLIST="0 1 2 3 4 5 6 7" XPERM=600 X#CLONEMAJOR=37 # is this standard ? X#CLONENAME=x # dont change X X# ---- do not change below this line ---- XMIDF="/tmp/MODULE_ID" XID=$1 XTYPE=$2 X Xif( test $# -lt 2 ) then X echo "Indirect Usage is: modload -exec $0 module.o" X exit 1 Xfi X#----------------------------------------------------- Xcase $TYPE in X X 12345600) X # DRIVER X BMAJOR=$3 X CMAJOR=$4 X for MINOR in $CMINORLIST X do X DEV=$CDEVICE$MINOR X echo "$0: replace \"$DEV\"." X rm -f $DEV X mknod $DEV c $CMAJOR $MINOR X chmod $PERM $DEV # for now X done X # CLONE stuff X # DEV=$CDEVICE$CLONENAME X # echo "$0: replace \"$DEV\" (CLONED CLONEMAJOR=$CLONEMAJOR)" X # rm -f $DEV X # mknod $DEV c $CLONEMAJOR $CMAJOR X # chmod $PERM $DEV # for now X ;; X X 12345607) X # PSEUDO X BMAJOR=$3 X CMAJOR=$4 X for MINOR in $CMINORLIST X do X DEV=$CDEVICE$MINOR X echo "$0: replace \"$DEV\"." X rm -f $DEV X mknod $DEV c $CMAJOR $MINOR X chmod $PERM $DEV # for now X done X # CLONE stuff X # DEV=$CDEVICE$CLONENAME X # echo "$0: replace \"$DEV\" (CLONED CLONEMAJOR=$CLONEMAJOR)" X # rm -f $DEV X # mknod $DEV c $CLONEMAJOR $CMAJOR X # chmod $PERM $DEV # for now X ;; X X 12345606) X # USER X ;; X X *) # ILLEGAL X echo "$0: illegal module type \"$TYPE\" from modload" X exit 1 X ;; Xesac X#----------------------------------------------------- Xecho $ID > $MIDF Xexit 0 SHAR_EOF $TOUCH -am 0322215092 load && chmod 0444 load || echo "restore of load failed" set `wc -c load`;Wc_c=$1 if test "$Wc_c" != "1529"; then echo original size 1529, current size $Wc_c fi # ============= unload ============== echo "x - extracting unload (Text)" sed 's/^X//' << 'SHAR_EOF' > unload && X#! /bin/sh X# @(#)unload 1.24 3/22/92 X XPATH=/usr/ucb:/bin:/usr/bin:/usr/etc ; export PATH X XMIDF="/tmp/MODULE_ID" X Xif ( test -f $MIDF ) then X X if(modunload -id `cat $MIDF`) then X rm $MIDF X else X modstat X exit 1 X fi Xelse X echo "no $MIDF file present" X exit 1 Xfi Xexit 0 SHAR_EOF $TOUCH -am 0322215092 unload && chmod 0444 unload || echo "restore of unload failed" set `wc -c unload`;Wc_c=$1 if test "$Wc_c" != "271"; then echo original size 271, current size $Wc_c fi # ============= tap.c ============== echo "x - extracting tap.c (Text)" sed 's/^X//' << 'SHAR_EOF' > tap.c && X/* X * tap streams-module/driver kernel-loadable-module, aka WATER-WORKS X * this is a combination of a STREAMS-module and a STREAMS-driver. X * X * Simon Ney -- neural@cs.tu-berlin.de -- simon@bbisun.uu.sub.org X */ X X#include "tap.h" X#if NTAP > 0 X#include X#include X#include X#include X#include X#include X#include X#include /*XX*/ X#ifdef TAPVD X#include X#include X#endif TAPVD X X#ifndef lint Xstatic char sccsid[] = "@(#)tap.c 1.24 3/22/92"; X#endif X X/* X * --- DRIVER PART --- X */ X X#ifdef TAPVDDUAL Xstatic struct module_info cminfo = { 0, "tapcvd", 0, INFPSZ, 0, 0 }; X#else Xstatic struct module_info cminfo = { 0, "tapc", 0, INFPSZ, 0, 0 }; X#endif X Xstatic int tapcopen(), tapcrput(), tapcwput(), tapcclose(); X Xstatic struct qinit crinit = { X tapcrput, NULL, tapcopen, tapcclose, NULL, &cminfo, NULL X}; X Xstatic struct qinit cwinit = { X tapcwput, NULL, NULL, NULL, NULL, &cminfo, NULL X}; X X#ifdef TAPVD /* so we can have a permanent linked AND loadable version */ Xstruct streamtab tapcvdinfo = { &crinit, &cwinit, NULL, NULL }; X#else Xstruct streamtab tapcinfo = { &crinit, &cwinit, NULL, NULL }; X#endif X X/* X * --- MODULE PART --- X */ X X#ifdef TAPVDDUAL Xstatic struct module_info minfo = { 0, "tapvd", 0, INFPSZ, 0, 0 }; X#else Xstatic struct module_info minfo = { 0, "tap", 0, INFPSZ, 0, 0 }; X#endif X Xstatic int tapopen(), taprput(), tapwput(), tapclose(); X Xstatic struct qinit rinit = { X taprput, NULL, tapopen, tapclose, NULL, &minfo, NULL X}; X Xstatic struct qinit winit = { X tapwput, NULL, NULL, NULL, NULL, &minfo, NULL X}; X X#ifdef TAPVD /* so we can have a permanent linked AND loadable version */ Xstruct streamtab tapvdinfo = { &rinit, &winit, NULL, NULL }; X#else Xstruct streamtab tapinfo = { &rinit, &winit, NULL, NULL }; X#endif X X/* X * the ,,TAP device'' structure X */ X Xstruct tap { X queue_t *tapdm_queue; /* queue from driver to module (set by module)*/ X queue_t *tapmd_queue; /* queue from module to driver (set by driver)*/ X#define TAP_REVERSE 1 /* if set connect to lower side else upper */ X unsigned int tap_flags; /* currently only the TAP_REVERSE flag */ X}; Xstatic struct tap tap_tap[NTAP]; /* static for now */ Xstatic int tap_cnt = NTAP; X X/* X * --- KERNEL-LOADABLE-MODULE SUPPORT --- X */ X X#ifdef TAPVD Xextern int nodev(); X Xstatic struct cdevsw tap_cdevsw = { X nodev, nodev, nodev, nodev, nodev, nodev, nodev, 0, X &tapcvdinfo, 0 X}; X Xstatic struct vdldrv tapvdldrv = { X VDMAGIC_PSEUDO, "tapc/tap-1.24", X NULL, X#ifndef sun4c X NULL, NULL, 0, 1, X#endif X NULL, &tap_cdevsw, 0, 0 X}; X X/* X * this is the pushable-STREAMS-module kernel-module-loader X */ Xstatic struct fmodsw *saved_fmp; X Xstatic struct fmodsw *loadfmodsw(name,str) Xchar *name; Xstruct streamtab *str; X{ X register struct fmodsw *fmp; X register int i; X extern struct fmodsw fmodsw[]; X extern int fmodcnt; X X fmp = fmodsw; X for(i=0;if_str==0){ X strcpy(fmp->f_name,name); X fmp->f_str = str; X return(fmp); X } X } X printf("tap: loadfmodsw: no free slot for '%s'\n",name); X return(0); X} X Xstatic unloadfmodsw(fmp) X struct fmodsw *fmp; X{ X fmp->f_name[0] = '\0'; X fmp->f_str = 0; X} X X/* X * this is the driver entry point routine. the name of the default entry X * point is xxxinit. it can be changed by using the "-entry" command to X * modload. X */ X Xxxxinit(function_code,vdp,vdi,vds) Xunsigned int function_code; Xstruct vddrv *vdp; Xaddr_t vdi; Xstruct vdstat *vds; X{ X register int i; X register struct tap *tap; X X switch(function_code){ X case VDLOAD: X if(saved_fmp){ /* ever occured */ X printf("tap: xxxinit:already loaded\n"); X return(ENXIO); X } X#ifdef TAPVDDUAL X if(!(saved_fmp=loadfmodsw("tapvd",&tapvdinfo))){ X#else X if(!(saved_fmp=loadfmodsw("tap",&tapvdinfo))){ X#endif X return(ENXIO); X } X vdp->vdd_vdtab = (struct vdlinkage *) &tapvdldrv; X break; X case VDUNLOAD: X for(i=0,tap=tap_tap;itapdm_queue||tap->tapmd_queue) X return(EBUSY); X if(saved_fmp) X unloadfmodsw(saved_fmp); X break; X case VDSTAT: X#ifdef TAPDEBUG X for(i=0,tap=tap_tap;itapdm_queue||tap->tapmd_queue) X printf( "tap%d: dm=0x%x md=0x%x flags=0x%x\n", X i,tap->tapdm_queue,tap->tapmd_queue, X tap->tap_flags); X#endif X break; X default: X return(EIO); X } X return(0); /* return success */ X} X#endif TAPVD X X/* --- MODULE PART --- */ X Xstatic int tapopen(q, dev, flag, sflag) X queue_t *q; X dev_t dev; X int flag; X int sflag; X{ X register int i; X register struct tap *tap; X X if(!(q->q_ptr)){ X /* X * find first fit free slot X */ X for(i=0,tap=tap_tap;itapdm_queue)){ X WR(q)->q_ptr = (char *) tap; X q->q_ptr = (char *) tap; /* mark as open */ X tap->tapdm_queue = q; X return(0); X } X } X return(OPENFAIL); X } X return(0); X} X Xstatic int tapwput(q, mp) X queue_t *q; X mblk_t *mp; X{ X mblk_t *bp; X struct tap *tap; X X tap = (struct tap *)q->q_ptr; X X if((!(tap->tap_flags&TAP_REVERSE))&&tap->tapmd_queue){ X if(mp->b_datap->db_type==M_DATA){ X if((bp=dupmsg(mp))!=NULL){ X putnext(tap->tapmd_queue,bp); X } X } X } X putnext(q,mp); X} X Xstatic int taprput(q, mp) X queue_t *q; X mblk_t *mp; X{ X mblk_t *bp; X struct tap *tap; X X tap = (struct tap *)q->q_ptr; X X if((tap->tap_flags&TAP_REVERSE)&&tap->tapmd_queue){ X if(mp->b_datap->db_type==M_DATA){ X if((bp=dupmsg(mp))!=NULL){ X putnext(tap->tapmd_queue,bp); X } X } X } X putnext(q, mp); X} X Xstatic int tapclose(q, flag) X queue_t *q; X int flag; X{ X struct tap *tap; X X tap = (struct tap *)q->q_ptr; X /* here i want to send a HANGUP */ X tap->tapdm_queue = NULL; X} X X/* --- DRIVER PART --- */ X Xstatic int tapcopen(q, dev, flag, sflag) X queue_t *q; X dev_t dev; X int flag; X int sflag; X{ X struct tap *tap; X X#ifdef TAPCLONE X /* X * if CLONEOPEN, pick first unconnected module. X * otherwise, check the minor device range. X */ X printf("tapopen: q=0x%x dev=%d flag=%d sflag=%d\n",q,dev,flag,sflag); X if(sflag==CLONEOPEN) { X for(dev=0;dev= tap_cnt) X return(OPENFAIL); X if(q->q_ptr){ X u.u_error = EBUSY; /* only 1 user of tapc at a time ??? */ X return(OPENFAIL); X } X X tap = &tap_tap[dev]; X if(!(tap->tapdm_queue)){ X u.u_error = ENETUNREACH; X return(OPENFAIL); X } X X /* X * if opened with O_NDELAY reverse the connection X */ X if(flag&FNDELAY){ X if(!suser()){ X u.u_error = EACCES; X return(OPENFAIL); X } X tap->tap_flags |= TAP_REVERSE; X } else X tap->tap_flags &= ~TAP_REVERSE; X X WR(q)->q_ptr = (char *)tap; X q->q_ptr = (char *)tap; X tap->tapmd_queue = q; X return(dev); X} X Xstatic int tapcwput(q, mp) X queue_t *q; X mblk_t *mp; X{ X switch(mp->b_datap->db_type){ X case M_IOCTL: { /* NAK all ioctl's */ X /* struct iocblk *iocp; */ X X /* iocp = (struct iocblk *)mp->b_rptr; */ X mp->b_datap->db_type=M_IOCNAK; X qreply(q,mp); X break; X } X case M_FLUSH: X if(*mp->b_rptr & FLUSHW) X flushq(q,0); X if(*mp->b_rptr & FLUSHR){ X flushq(RD(q),0); X *mp->b_rptr &= ~FLUSHW; X qreply(q,mp); X } else X freemsg(mp); X break; X case M_DATA: { X struct tap *tap; X X tap = (struct tap *)q->q_ptr; X if(tap->tapdm_queue) { X if(tap->tap_flags&TAP_REVERSE) X putnext(WR(tap->tapdm_queue), mp); X else X putnext(tap->tapdm_queue, mp); X } else { X (void)putctl1(RD(q)->q_next, M_ERROR, ECONNRESET); X freemsg(mp); X } X break; X } X X default: /* discard other messages */ X freemsg(mp); X } X} X Xstatic int tapcrput(q, mp) X queue_t *q; X mblk_t *mp; X{ X putnext(q, mp); X} X Xstatic int tapcclose(q, flag) X queue_t *q; X int flag; X{ X struct tap *tap; X X tap = (struct tap *) q->q_ptr; X tap->tapmd_queue = NULL; X} X X#endif NTAP SHAR_EOF $TOUCH -am 0322215092 tap.c && chmod 0444 tap.c || echo "restore of tap.c failed" set `wc -c tap.c`;Wc_c=$1 if test "$Wc_c" != "8013"; then echo original size 8013, current size $Wc_c fi # ============= tap.h ============== echo "x - extracting tap.h (Text)" sed 's/^X//' << 'SHAR_EOF' > tap.h && X/* X * @(#)tap.h 1.24 3/22/92 X */ X X/* X * NOTE: X * this header file is only needed for the loadable version of the driver X * if the driver is linked permanently to vmunix this file is generated X * by config(1) X */ X X#define NTAP 8 /* see also : ./load at CMINORLIST */ SHAR_EOF $TOUCH -am 0322215092 tap.h && chmod 0444 tap.h || echo "restore of tap.h failed" set `wc -c tap.h`;Wc_c=$1 if test "$Wc_c" != "268"; then echo original size 268, current size $Wc_c fi # ============= tapmon.c ============== echo "x - extracting tapmon.c (Text)" sed 's/^X//' << 'SHAR_EOF' > tapmon.c && X/* X * read/write /dev/tapc* utility X */ X#include X/* #include */ X#include X/* #include */ X#include X#include X#include X X#define STDIN 0 X#define STDOUT 1 X X#define NAME "/dev/tapc%d" X#define CLONENAME "/dev/tapcx" X X#define ESCAPE 31 /* CTRL-_ */ X X#ifndef lint Xstatic char sccsid[] = "@(#)tapmon.c 1.24 3/22/92"; X#endif X Xchar *myname; X Xint viatty; Xstruct termios old,new; X Xusage() X{ X (void)fprintf(stderr,"Usage: %s [-r] \n",myname); X (void)fprintf(stderr," tap-id: 0-255|x\n"); X exit(1); X} X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X unsigned long id; X int f,r; X char name[sizeof(NAME)+3]; X char *ptr; X int c,errflg=0,reverse=0; X extern char *optarg; X extern int optind; X X myname=argv[0]; X X X while ((c = getopt(argc, argv, "r")) != -1){ X switch (c) { X case 'r': X reverse++; X break; X case '?': X default: X errflg++; X } X } X if (errflg||(optind+1)!=argc) { X usage(); X } X X if(!strcmp(argv[optind],"x")) X sprintf(name,CLONENAME); X else { X id=strtol(argv[optind],&ptr,0); X if(id>255||*ptr!='\0') X usage(); X sprintf(name,NAME,id); X } X X if((f=open(name,O_RDWR|(reverse?O_NDELAY:0)))<0){ X perror(name); X exit(1); X } X X ttyset(name); X r=connect(f); X close(f); X ttyreset(); X return(r); X} X Xttyset(name) Xchar *name; X{ X if(isatty(STDIN)){ X viatty=1; X fprintf(stderr,"CONNECTED TO %s\n",name); X fprintf(stderr,"ESCAPE CHARACTER IS CTRL-%c\n",ESCAPE+'@'); X if(ioctl(STDIN,TCGETS,&old)==(-1)){ X perror("TCGETS"); X exit(1); X } X new=old; X new.c_iflag = 0; X /* new.c_oflag = 0;*/ X new.c_lflag = 0; X if(ioctl(STDIN,TCSETS,&new)==(-1)){ X perror("TCSETS"); X exit(1); X } X } X} X Xttyreset() X{ X if(viatty){ X if(ioctl(STDIN,TCSETS,&old)==(-1)){ X perror("TCSETS"); X exit(1); X } X fprintf(stderr,"\nCONNECTION CLOSED\n"); X } X} X Xconnect(f) X{ X register int n,s; X int x,w; X fd_set fdset; X char buf[512]; X X s=sizeof(buf); X w=f+1; X FD_ZERO(&fdset); X FD_SET(STDIN,&fdset); X FD_SET(f,&fdset); X X while((x=select(w,&fdset,NULL,NULL,NULL))){ X if( FD_ISSET (f, &fdset)){ X if(ioctl(f,FIONREAD,&n)==(-1)){ X perror(myname); X return(10); X } X if(!n) X break; X n = (n streams.c && X X#include X#include X X#ifndef lint Xstatic char sccsid[] = "@(#)streams.c 1.24 3/22/92"; X#endif X Xint silence = 0; X Xpop(fd,namewanted) Xchar *namewanted; X{ X char name[64]; X X if(ioctl(fd, I_LOOK, name) != -1) { X if(!strcmp(name,namewanted)){ X if(!silence) X (void)fprintf(stderr,"popping module: %s\n", name); X if(ioctl(fd,I_POP,0) == -1) X if(!silence) X perror("ioctl I_POP"); X }else{ X X if(!silence) X (void)fprintf(stderr, X "module %s not pop,module %s is on stack top\n", X namewanted,name); X } X } else { X if(!silence) X (void)fprintf(stderr,"no module on stack\n"); X } X} X Xpush(fd,name) Xchar *name; X{ X int r; X X if(!silence) X (void)fprintf(stderr,"pushing module: %s\n", name); X if ((r=ioctl(fd, I_PUSH, name)) < 0) X if(!silence) X perror(name); X} X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int c,errflg=0; X extern char *optarg; X extern int optind; X X while ((c = getopt(argc, argv, "so:u:")) != -1){ X switch (c) { X case 'o': X pop(0,optarg); X break; X case 'u': X push(0,optarg); X break; X case 's': X silence = ~silence; X break; X case '?': X default: X errflg++; X } X } X if (errflg||optind!=argc||argc==1) { X (void)fprintf(stderr, X "Usage: %s [-s] [-o module-to-pop] [-u module-to-push] ...\n", X argv[0]); X (void)fprintf(stderr, X " the order of all options is important\n"); X exit (2); X } X return(0); X} SHAR_EOF $TOUCH -am 0322215092 streams.c && chmod 0444 streams.c || echo "restore of streams.c failed" set `wc -c streams.c`;Wc_c=$1 if test "$Wc_c" != "1387"; then echo original size 1387, current size $Wc_c fi exit 0 -- Simon Ney -- neural@cs.tu-berlin.de -- simon@bbisun.uu.sub.org