From: deraadt@newt.cuc.ab.ca (Theo de Raadt)
Subject: Re: rpc process chewing up resources
Organization: little lizard city
Date: Thu, 5 Nov 1992 11:44:04 GMT

I'm currently implimenting YP client functionality for 386bsd. So far,
it's been an enjoyable and frustrating time....

In article <49256@shamash.cdc.com> gsa@easyaspi.udev.cdc.com (gary s anderson) writes:
>  |> > |> > sits within the "yp" library code (you need to ask SUN why "pinging"
>  |> > |> > the portmapper from within "yp" is useful).  This has the wonderful
>  |> > |> Hmmmph!
>  |> > |> What would you do if you wanted to discover if ypbind is running?

Well, on some systems (including my code at the moment) that's exactly
why TCP is used. It's faster than UDP.

My first code used UDP to find out if ypbind was running. Well, if you
don't get an answer, even in talking to 127.0.0.1, well, the kernel's
buffers could just be swamped at the moment. So you have to try a few
times. Not pretty.

So, I started using TCP. Immediate response yes/no whether YP is
running. I had no real concerns with whether the portmapper is
running.

I'm have a Sun too. A few minutes ago, I went and looked to see why
the file /etc/ypbind.lock exist... a bit of snooping and following a
hunch...

  4835 -rw-------  1 root            0 Nov  2 21:46 /etc/ypbind.lock
  ^^^^
 inode

pstat -i | grep 4835
 f23f9a8    R     7,  0  4835 100600   1    0         0   E     2   0   1 VREG
							  ^^^
That little 'E' is an exclusive lock.

Could someone explain exactly what is going on here? What I suspect
follows: ypbind maintains the exclusive lock on /etc/ypbind.lock
Processes that are interested can find out if ypbind is running by
doing a lockf(fd, F_TEST).  Sun's ypbind also puts an exclusive lock
on /var/yp/binding/domainname.2 and /var/yp/binding/domainname.1.  I
suspect the 2 is YPBINDVERS.

Just trying to get a flock() on that file seems to work. This is so much
easier than what it appears the entire argument here is about.

Here's what happens if I trace a program that needs to check YP.

    open ("/var/yp/binding/cuc.ab.ca.2", 0, 036736173730) = 4
    flock (4, 06) = -1 EWOULDBLOCK (Operation would block)
    mmap (0x8ab8, 14, 0x1, 0x80000001, 4, 0) = 0xf7710000
    close (4) = 0

Aha. The fact that the flock() failed tells us that ypbind is running.
Sun places into the binding file the actual (struct sockaddr_in) at
which the current ypserver can be found (It could be ypbind's address,
but it makes more sense to be ypserv's address). So they mmap() the
(struct sockaddr_in) and continue.

>  |> > 
>  |> > I would send a UDP RPC request to the portmapper to find out
>  |> > if ypbind was registered.  The problem is that there is code
>  |> > which creates a "dummy" TCP connection just to see if the
>  |> > portmapper is running (i.e. doesn't trust UDP time-outs as 
>  |> > sufficient evidence that the portmapper is not running).

I would not trust a UDP timeout on "localhost" as meaning that the
portmapper is dead. It might take 5 seconds for a busy portmapper to
answer. Someone in Timbuktu, at the end of a very slow link, may have
been spraying the portmapper. Packets may have convoyed, and the
portmapper may be swamped! How long are you going to wait around?

>  |> > If the connection succeeds, it is immediately closed and then
>  |> > the UDP RPC request is made to the portmapper to get the 
>  |> > information about ypbind.
>  |> 
>  |> Perhaps my point was not clear.
>  |> 
>  |> By using TCP you avoid having to wait for a UDP time-out to expire when
>  |> things are not present.  Which would make you more unhappy?  Having an
>  |> anonymous TCP port number tied up for a little while or having to wait
>  |> a large part of a second (or more if you allow remote access over slow
>  |> links) to discover that the portmapper is not running?

With TCP, your connection will succeed immediately, well, as long as
the listen queue has room for you....


Really, I prefer Sun's method of checking for yellow. A flock() on a
locked file means you are talking to an inode that is already in the
buffer cache. That's got to be faster and more reliable than talking
to portmap & ypbind.

Anyways, I'm going to impliment my routines much like Sun's did!

Only one thing bothers me with the RPC programming I am doing. Sun's
ypbind is not multithreaded; rather, it forks when it gets a request
for a currently unbound domain. I decided to make my ypbind much more
multithreaded. What I have come to discover to my disgust is that if
you wish to write a properly multithreaded RPC application you have to
give up all the juicy RPC and SVC routines and dig right into the XDR
level. What a pain. And, boy, I could scream because I have found no
way to access msg->msg_xid from the SVC/RPC level! For a proper
multi-threaded application, you are going to need to save a copy of
that for the later reply!
 <tdr.
--

This space not left unintentionally unblank.		deraadt@newt.cuc.ab.ca