Subject: Re: How to support clone devices (i.e. /dev/tcp)
To: Gordon Ross <gwr@mc.com>
From: Christos Zoulas <christos@deshaw.com>
List: tech-kern
Date: 11/15/1994 11:39:54
On Nov 15, 11:10am, gwr@jericho.mc.com (Gordon W. Ross) wrote:
-- Subject: How to support clone devices (i.e. /dev/tcp)

| > >Was this discussed anywhere?  (like tech-kern?)
| 
| > I sent mail to core a couple of weeks ago. I received two replies which
| > said it was ok to proceed.
| 
| OK, I'm just surprised there was no discussion on tech-kern first.

I was not sure what the proper channels were. I'll do that next time.

| > >Why was this change done?
| > 
| > To implement cloning devices [needed for svr4 /dev/{tcp,udp,...}
| 
| > If you think that this is not the right way to do it and you provide an
| > alternative implementation that does not change half the files in sys
| > I am all for it.
| 
| Well, it's probably too late to consider, but another way to allow
| svr4 programs using -lsocket and -lnsl to work would be to write a
| special libsocket.so that interfaces to the BSD socket calls.
| If one really needs libnsl.so (and I doubt it) then that too could
| be implemented as a layer on top of the BSD socket calls.
| This would avoid the need for a kernel-level interface for the
| cloning devices (/dev/tcp, /dev/udp).  Did you consider this?
| (I could write the libsocket.so if someone wants me to.)

Well, not everything uses libsocket.so; actually almost nothing except
XFree86 and the berkeley utilities [telnet,rlogin,rsh].  Most of the
commercial stuff including the version of X that comes bundled with the
OS and framemaker uses libnsl.so directly.

| If we just want clone open capabilities for the fun of it,
| I like the SunOS method for allowing a driver to do cloning:
| 
|   int xxx_open(dev_t *devp, int flag, int otyp, cred_t *credp);
| 
| The key to it is that the first arg is a pointer to a dev_t
| that the driver may modify during open.  The dev_t provided
| is the one from the device node (i.e. minor zero) but if the
| driver sets it to (i.e.) minor 4 (because that was the first
| available minor unit) then the specfs layer makes a new vnode
| for this open file and things continue from there.

But for /dev/udp and /dev/tcp there is no corresponding vnode.
The solution I proposed is much more general; by passing struct file *
in directly, the open routine can do anything it wants with it.

| I think the above interface can be implemented without any
| changes outside the specfs module (though I'm not sure).

You would need to change *every* device driver open() routine to take
a pointer to a dev_t instead of dev_t itself. Plus all the files I had
to change for my changes...

In any case; I have /dev/tcp and /dev/udp mostly working; well enough
to run X clients [xclock] and telnet directly using /dev/tcp and
nslookup using /dev/udp...

Pretty amazing how few streams calls I needed to implement to make
libnsl.so happy!

christos